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.1 by root, Fri Feb 3 07:11:38 2006 UTC vs.
Revision 1.8 by elmex, Fri Aug 11 12:50:36 2006 UTC

1/* 1/*
2 * static char *rcsid_object_c = 2 * static char *rcsid_object_c =
3 * "$Id: object.c,v 1.1 2006/02/03 07:11:38 root Exp $"; 3 * "$Id: object.c,v 1.8 2006/08/11 12:50:36 elmex 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
52 52
53object *objects; /* Pointer to the list of used objects */ 53object *objects; /* Pointer to the list of used objects */
54object *free_objects; /* Pointer to the list of unused objects */ 54object *free_objects; /* Pointer to the list of unused objects */
55object *active_objects; /* List of active objects that need to be processed */ 55object *active_objects; /* List of active objects that need to be processed */
56 56
57void (*object_free_callback)(object *ob);
57 58
58short freearr_x[SIZEOFFREE]= 59short freearr_x[SIZEOFFREE]=
59 {0,0,1,1,1,0,-1,-1,-1,0,1,2,2,2,2,2,1,0,-1,-2,-2,-2,-2,-2,-1, 60 {0,0,1,1,1,0,-1,-1,-1,0,1,2,2,2,2,2,1,0,-1,-2,-2,-2,-2,-2,-1,
60 0,1,2,3,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1}; 61 0,1,2,3,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1};
61short freearr_y[SIZEOFFREE]= 62short freearr_y[SIZEOFFREE]=
68 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,
69 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};
70 71
71 72
72/* 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. */
73static int compare_ob_value_lists_one(object * wants, object * has) { 74static int compare_ob_value_lists_one(const object * wants, const object * has) {
74 key_value * wants_field; 75 key_value * wants_field;
75 76
76 /* 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
77 * 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
78 * different structure or at least keep the lists sorted... 79 * different structure or at least keep the lists sorted...
102 /* 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. */
103 return TRUE; 104 return TRUE;
104} 105}
105 106
106/* Returns TRUE if ob1 has the same key_values as ob2. */ 107/* Returns TRUE if ob1 has the same key_values as ob2. */
107static int compare_ob_value_lists(object * ob1, object * ob2) { 108static int compare_ob_value_lists(const object * ob1, const object * ob2) {
108 /* 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,
109 * so we need to run the comparison *twice*. :( 110 * so we need to run the comparison *twice*. :(
110 */ 111 */
111 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);
112} 113}
197 (ob1->materialname != ob2->materialname) || 198 (ob1->materialname != ob2->materialname) ||
198 (ob1->lore != ob2->lore) || 199 (ob1->lore != ob2->lore) ||
199 (ob1->subtype != ob2->subtype) || 200 (ob1->subtype != ob2->subtype) ||
200 (ob1->move_type != ob2->move_type) || 201 (ob1->move_type != ob2->move_type) ||
201 (ob1->move_block != ob2->move_block) || 202 (ob1->move_block != ob2->move_block) ||
203 (ob1->move_allow != ob2->move_allow) ||
202 (ob1->move_on != ob2->move_on) || 204 (ob1->move_on != ob2->move_on) ||
203 (ob1->move_off != ob2->move_off) || 205 (ob1->move_off != ob2->move_off) ||
204 (ob1->move_slow != ob2->move_slow) || 206 (ob1->move_slow != ob2->move_slow) ||
205 (ob1->move_slow_penalty != ob2->move_slow_penalty) 207 (ob1->move_slow_penalty != ob2->move_slow_penalty)
206 ) 208 )
211 * some items equipped, and we don't want those to merge. 213 * some items equipped, and we don't want those to merge.
212 */ 214 */
213 if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED)) 215 if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED))
214 return 0; 216 return 0;
215 217
218 switch (ob1->type) {
219 case SCROLL:
220 if (ob1->level != ob2->level) return 0;
221 break;
222
223 }
216 if (ob1->key_values != NULL || ob2->key_values != NULL) { 224 if (ob1->key_values != NULL || ob2->key_values != NULL) {
217 /* At least one of these has key_values. */ 225 /* At least one of these has key_values. */
218 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) { 226 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) {
219 /* One has fields, but the other one doesn't. */ 227 /* One has fields, but the other one doesn't. */
220 return 0; 228 return 0;
221 } else {
222 return compare_ob_value_lists(ob1, ob2); 229 } else if (!compare_ob_value_lists(ob1, ob2)) {
230 return 0;
223 } 231 }
224 } 232 }
225 233
226 switch (ob1->type) {
227 case SCROLL:
228 if (ob1->level != ob2->level) return 0;
229 break;
230
231 }
232 /* Everything passes, must be OK. */ 234 /* Everything passes, must be OK. */
233 return 1; 235 return 1;
234} 236}
235 237
236/* 238/*
384 * 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
385 * multi-object 1 which is closest to the second object. 387 * multi-object 1 which is closest to the second object.
386 * If it's not a multi-object, it is returned. 388 * If it's not a multi-object, it is returned.
387 */ 389 */
388 390
389object *get_nearest_part(object *op,object *pl) { 391object *get_nearest_part(object *op, const object *pl) {
390 object *tmp,*closest; 392 object *tmp,*closest;
391 int last_dist,i; 393 int last_dist,i;
392 if(op->more==NULL) 394 if(op->more==NULL)
393 return op; 395 return op;
394 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)
413 * 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.
414 * Used only by the patch command, but not all that useful. 416 * Used only by the patch command, but not all that useful.
415 * Enables features like "patch <name-of-other-player> food 999" 417 * Enables features like "patch <name-of-other-player> food 999"
416 */ 418 */
417 419
418object *find_object_name(char *str) { 420object *find_object_name(const char *str) {
419 const char *name=add_string(str); 421 const char *name=add_string(str);
420 object *op; 422 object *op;
421 for(op=objects;op!=NULL;op=op->next) 423 for(op=objects;op!=NULL;op=op->next)
422 if(op->name==name) 424 if(op->name==name)
423 break; 425 break;
1018 if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE)) 1020 if (QUERY_FLAG(op, FLAG_ALIVE) && !(flags & P_IS_ALIVE))
1019 update_now=1; 1021 update_now=1;
1020 1022
1021 if ((move_on | op->move_on) != move_on) update_now=1; 1023 if ((move_on | op->move_on) != move_on) update_now=1;
1022 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 */
1023 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;
1024 if ((move_slow | op->move_slow) != move_slow) update_now=1; 1030 if ((move_slow | op->move_slow) != move_slow) update_now=1;
1025 } 1031 }
1026 /* if the object is being removed, we can't make intelligent 1032 /* if the object is being removed, we can't make intelligent
1027 * decisions, because remove_ob can't really pass the object 1033 * decisions, because remove_ob can't really pass the object
1028 * that is being removed. 1034 * that is being removed.
1060void free_object(object *ob) { 1066void free_object(object *ob) {
1061 free_object2(ob, 0); 1067 free_object2(ob, 0);
1062} 1068}
1063void free_object2(object *ob, int free_inventory) { 1069void free_object2(object *ob, int free_inventory) {
1064 object *tmp,*op; 1070 object *tmp,*op;
1071
1072 if (object_free_callback)
1073 object_free_callback (ob);
1065 1074
1066 if (!QUERY_FLAG(ob,FLAG_REMOVED)) { 1075 if (!QUERY_FLAG(ob,FLAG_REMOVED)) {
1067 LOG(llevDebug,"Free object called with non removed object\n"); 1076 LOG(llevDebug,"Free object called with non removed object\n");
1068 dump_object(ob); 1077 dump_object(ob);
1069#ifdef MANY_CORES 1078#ifdef MANY_CORES
1507 if(op->more!=NULL) { 1516 if(op->more!=NULL) {
1508 /* The part may be on a different map. */ 1517 /* The part may be on a different map. */
1509 1518
1510 object *more = op->more; 1519 object *more = op->more;
1511 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)) {
1512 /* 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 */
1513 more->ox = more->x; 1528 more->ox = more->x;
1514 more->oy = more->y; 1529 more->oy = more->y;
1515 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 }
1516 1537
1517 if (insert_ob_in_map(more, more->map, originator, flag) == NULL) { 1538 if (insert_ob_in_map(more, more->map, originator, flag) == NULL) {
1518 if ( ! op->head) 1539 if ( ! op->head)
1519 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");
1520 return NULL; 1541 return NULL;
1523 CLEAR_FLAG(op,FLAG_REMOVED); 1544 CLEAR_FLAG(op,FLAG_REMOVED);
1524 1545
1525 /* Debugging information so you can see the last coordinates this object had */ 1546 /* Debugging information so you can see the last coordinates this object had */
1526 op->ox=op->x; 1547 op->ox=op->x;
1527 op->oy=op->y; 1548 op->oy=op->y;
1549
1550 /* Ideally, the caller figures this out. However, it complicates a lot
1551 * of areas of callers (eg, anything that uses find_free_spot would now
1552 * need extra work
1553 */
1554 op->map=get_map_from_coord(m, &op->x, &op->y);
1528 x = op->x; 1555 x = op->x;
1529 y = op->y; 1556 y = op->y;
1530 op->map=get_map_from_coord(m, &x, &y);
1531 1557
1532 /* this has to be done after we translate the coordinates. 1558 /* this has to be done after we translate the coordinates.
1533 */ 1559 */
1534 if(op->nrof && !(flag & INS_NO_MERGE)) { 1560 if(op->nrof && !(flag & INS_NO_MERGE)) {
1535 for(tmp=GET_MAP_OB(op->map,x,y);tmp!=NULL;tmp=tmp->above) 1561 for(tmp=GET_MAP_OB(op->map,x,y);tmp!=NULL;tmp=tmp->above)
1536 if (CAN_MERGE(op,tmp)) { 1562 if (CAN_MERGE(op,tmp)) {
1537 op->nrof+=tmp->nrof; 1563 op->nrof+=tmp->nrof;
1538 remove_ob(tmp); 1564 remove_ob(tmp);
1539 free_object(tmp); 1565 free_object(tmp);
1540 } 1566 }
1541 }
1542
1543 /* Ideally, the caller figures this out. However, it complicates a lot
1544 * of areas of callers (eg, anything that uses find_free_spot would now
1545 * need extra work
1546 */
1547 if (op->map != m) {
1548 /* coordinates should not change unless map also changes */
1549 op->x = x;
1550 op->y = y;
1551 } 1567 }
1552 1568
1553 CLEAR_FLAG(op,FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */ 1569 CLEAR_FLAG(op,FLAG_APPLIED); /* hack for fixing F_APPLIED in items of dead people */
1554 CLEAR_FLAG(op, FLAG_INV_LOCKED); 1570 CLEAR_FLAG(op, FLAG_INV_LOCKED);
1555 if (!QUERY_FLAG(op, FLAG_ALIVE)) 1571 if (!QUERY_FLAG(op, FLAG_ALIVE))
1585 */ 1601 */
1586 1602
1587 while (top != NULL) { 1603 while (top != NULL) {
1588 if (QUERY_FLAG(top, FLAG_IS_FLOOR) || 1604 if (QUERY_FLAG(top, FLAG_IS_FLOOR) ||
1589 QUERY_FLAG(top, FLAG_OVERLAY_FLOOR)) floor = top; 1605 QUERY_FLAG(top, FLAG_OVERLAY_FLOOR)) floor = top;
1590 if (QUERY_FLAG(top, FLAG_NO_PICK) && 1606 if (QUERY_FLAG(top, FLAG_NO_PICK)
1591 (top->move_type & (MOVE_FLY_LOW |MOVE_FLY_HIGH))) { 1607 && (top->move_type & (MOVE_FLY_LOW |MOVE_FLY_HIGH))
1608 && !QUERY_FLAG(top, FLAG_IS_FLOOR))
1609 {
1592 /* We insert above top, so we want this object below this */ 1610 /* We insert above top, so we want this object below this */
1593 top=top->below; 1611 top=top->below;
1594 break; 1612 break;
1595 } 1613 }
1614
1596 last = top; 1615 last = top;
1597 top = top->above; 1616 top = top->above;
1598 } 1617 }
1599 /* Don't want top to be NULL, so set it to the last valid object */ 1618 /* Don't want top to be NULL, so set it to the last valid object */
1600 top = last; 1619 top = last;
1613 if (!(flag & INS_ON_TOP) && 1632 if (!(flag & INS_ON_TOP) &&
1614 (get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL) & P_BLOCKSVIEW) && 1633 (get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL) & P_BLOCKSVIEW) &&
1615 (op->face && !op->face->visibility)) { 1634 (op->face && !op->face->visibility)) {
1616 for (last=top; last != floor; last=last->below) 1635 for (last=top; last != floor; last=last->below)
1617 if (QUERY_FLAG(last, FLAG_BLOCKSVIEW)&&(last->type != EXIT)) break; 1636 if (QUERY_FLAG(last, FLAG_BLOCKSVIEW)&&(last->type != EXIT)) break;
1618 /* Check to see i we found the object that blocks view, 1637 /* Check to see if we found the object that blocks view,
1619 * and make sure we have a below pointer for it so that 1638 * and make sure we have a below pointer for it so that
1620 * we can get inserted below this one, which requires we 1639 * we can get inserted below this one, which requires we
1621 * set top to the object below us. 1640 * set top to the object below us.
1622 */ 1641 */
1623 if (last && last->below && last != floor) top=last->below; 1642 if (last && last->below && last != floor) top=last->below;
1702 1721
1703/* this function inserts an object in the map, but if it 1722/* this function inserts an object in the map, but if it
1704 * finds an object of its own type, it'll remove that one first. 1723 * finds an object of its own type, it'll remove that one first.
1705 * op is the object to insert it under: supplies x and the map. 1724 * op is the object to insert it under: supplies x and the map.
1706 */ 1725 */
1707void replace_insert_ob_in_map(char *arch_string, object *op) { 1726void replace_insert_ob_in_map(const char *arch_string, object *op) {
1708 object *tmp; 1727 object *tmp;
1709 object *tmp1; 1728 object *tmp1;
1710 1729
1711 /* first search for itself and remove any old instances */ 1730 /* first search for itself and remove any old instances */
1712 1731
2080 * present_arch(arch, map, x, y) searches for any objects with 2099 * present_arch(arch, map, x, y) searches for any objects with
2081 * a matching archetype at the given map and coordinates. 2100 * a matching archetype at the given map and coordinates.
2082 * The first matching object is returned, or NULL if none. 2101 * The first matching object is returned, or NULL if none.
2083 */ 2102 */
2084 2103
2085object *present_arch(archetype *at, mapstruct *m, int x, int y) { 2104object *present_arch(const archetype *at, mapstruct *m, int x, int y) {
2086 object *tmp; 2105 object *tmp;
2087 if(m==NULL || out_of_map(m,x,y)) { 2106 if(m==NULL || out_of_map(m,x,y)) {
2088 LOG(llevError,"Present_arch called outside map.\n"); 2107 LOG(llevError,"Present_arch called outside map.\n");
2089 return NULL; 2108 return NULL;
2090 } 2109 }
2116 * present_in_ob(type, object) searches for any objects with 2135 * present_in_ob(type, object) searches for any objects with
2117 * a matching type variable in the inventory of the given object. 2136 * a matching type variable in the inventory of the given object.
2118 * The first matching object is returned, or NULL if none. 2137 * The first matching object is returned, or NULL if none.
2119 */ 2138 */
2120 2139
2121object *present_in_ob(unsigned char type,object *op) { 2140object *present_in_ob(unsigned char type, const object *op) {
2122 object *tmp; 2141 object *tmp;
2123 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) 2142 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
2124 if(tmp->type==type) 2143 if(tmp->type==type)
2125 return tmp; 2144 return tmp;
2126 return NULL; 2145 return NULL;
2139 * the object name, not the archetype name. this is so that the 2158 * the object name, not the archetype name. this is so that the
2140 * spell code can use one object type (force), but change it's name 2159 * spell code can use one object type (force), but change it's name
2141 * to be unique. 2160 * to be unique.
2142 */ 2161 */
2143 2162
2144object *present_in_ob_by_name(int type, char *str,object *op) { 2163object *present_in_ob_by_name(int type, const char *str, const object *op) {
2145 object *tmp; 2164 object *tmp;
2146 2165
2147 for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) { 2166 for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) {
2148 if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name))) 2167 if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name)))
2149 return tmp; 2168 return tmp;
2155 * present_arch_in_ob(archetype, object) searches for any objects with 2174 * present_arch_in_ob(archetype, object) searches for any objects with
2156 * a matching archetype in the inventory of the given object. 2175 * a matching archetype in the inventory of the given object.
2157 * The first matching object is returned, or NULL if none. 2176 * The first matching object is returned, or NULL if none.
2158 */ 2177 */
2159 2178
2160object *present_arch_in_ob(archetype *at, object *op) { 2179object *present_arch_in_ob(const archetype *at, const object *op) {
2161 object *tmp; 2180 object *tmp;
2162 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) 2181 for(tmp=op->inv;tmp!=NULL;tmp=tmp->below)
2163 if( tmp->arch == at) 2182 if( tmp->arch == at)
2164 return tmp; 2183 return tmp;
2165 return NULL; 2184 return NULL;
2219 * to know if the space in question will block the object. We can't use 2238 * to know if the space in question will block the object. We can't use
2220 * the archetype because that isn't correct if the monster has been 2239 * the archetype because that isn't correct if the monster has been
2221 * customized, changed states, etc. 2240 * customized, changed states, etc.
2222 */ 2241 */
2223 2242
2224int find_free_spot(object *ob, mapstruct *m,int x,int y,int start,int stop) { 2243int find_free_spot(const object *ob, mapstruct *m,int x,int y,int start,int stop) {
2225 int i,index=0, flag; 2244 int i,index=0, flag;
2226 static int altern[SIZEOFFREE]; 2245 static int altern[SIZEOFFREE];
2227 2246
2228 for(i=start;i<stop;i++) { 2247 for(i=start;i<stop;i++) {
2229 flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]); 2248 flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]);
2250 * find_free_spot(), but it will search max number of squares. 2269 * find_free_spot(), but it will search max number of squares.
2251 * But it will return the first available spot, not a random choice. 2270 * But it will return the first available spot, not a random choice.
2252 * Changed 0.93.2: Have it return -1 if there is no free spot available. 2271 * Changed 0.93.2: Have it return -1 if there is no free spot available.
2253 */ 2272 */
2254 2273
2255int find_first_free_spot(object *ob, mapstruct *m,int x,int y) { 2274int find_first_free_spot(const object *ob, mapstruct *m,int x,int y) {
2256 int i; 2275 int i;
2257 for(i=0;i<SIZEOFFREE;i++) { 2276 for(i=0;i<SIZEOFFREE;i++) {
2258 if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i])) 2277 if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]))
2259 return i; 2278 return i;
2260 } 2279 }
2361/* 2380/*
2362 * distance(object 1, object 2) will return the square of the 2381 * distance(object 1, object 2) will return the square of the
2363 * distance between the two given objects. 2382 * distance between the two given objects.
2364 */ 2383 */
2365 2384
2366int distance(object *ob1,object *ob2) { 2385int distance(const object *ob1, const object *ob2) {
2367 int i; 2386 int i;
2368 i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+ 2387 i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+
2369 (ob1->y - ob2->y)*(ob1->y - ob2->y); 2388 (ob1->y - ob2->y)*(ob1->y - ob2->y);
2370 return i; 2389 return i;
2371} 2390}
2376 * object, needs to travel toward it. 2395 * object, needs to travel toward it.
2377 */ 2396 */
2378 2397
2379int find_dir_2(int x, int y) { 2398int find_dir_2(int x, int y) {
2380 int q; 2399 int q;
2400
2381 if(!y) 2401 if(y)
2402 q=x*100/y;
2403 else if (x)
2382 q= -300*x; 2404 q= -300*x;
2383 else 2405 else
2384 q=x*100/y; 2406 return 0;
2407
2385 if(y>0) { 2408 if(y>0) {
2386 if(q < -242) 2409 if(q < -242)
2387 return 3 ; 2410 return 3 ;
2388 if (q < -41) 2411 if (q < -41)
2389 return 2 ; 2412 return 2 ;
2391 return 1 ; 2414 return 1 ;
2392 if (q < 242) 2415 if (q < 242)
2393 return 8 ; 2416 return 8 ;
2394 return 7 ; 2417 return 7 ;
2395 } 2418 }
2419
2396 if (q < -242) 2420 if (q < -242)
2397 return 7 ; 2421 return 7 ;
2398 if (q < -41) 2422 if (q < -41)
2399 return 6 ; 2423 return 6 ;
2400 if (q < 41) 2424 if (q < 41)
2401 return 5 ; 2425 return 5 ;
2402 if (q < 242) 2426 if (q < 242)
2403 return 4 ; 2427 return 4 ;
2428
2404 return 3 ; 2429 return 3 ;
2405} 2430}
2406 2431
2407/* 2432/*
2408 * absdir(int): Returns a number between 1 and 8, which represent 2433 * absdir(int): Returns a number between 1 and 8, which represent
2536 * core dumps if they do. 2561 * core dumps if they do.
2537 * 2562 *
2538 * Add a check so we can't pick up invisible objects (0.93.8) 2563 * Add a check so we can't pick up invisible objects (0.93.8)
2539 */ 2564 */
2540 2565
2541int can_pick(object *who,object *item) { 2566int can_pick(const object *who, const object *item) {
2542 return /*QUERY_FLAG(who,FLAG_WIZ)||*/ 2567 return /*QUERY_FLAG(who,FLAG_WIZ)||*/
2543 (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&& 2568 (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&&
2544 !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible && 2569 !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible &&
2545 (who->type==PLAYER||item->weight<who->weight/3)); 2570 (who->type==PLAYER||item->weight<who->weight/3));
2546} 2571}
2581 2606
2582 return dst; 2607 return dst;
2583} 2608}
2584 2609
2585/* return true if the object was destroyed, 0 otherwise */ 2610/* return true if the object was destroyed, 0 otherwise */
2586int was_destroyed (object *op, tag_t old_tag) 2611int was_destroyed (const object *op, tag_t old_tag)
2587{ 2612{
2588 /* checking for FLAG_FREED isn't necessary, but makes this function more 2613 /* checking for FLAG_FREED isn't necessary, but makes this function more
2589 * robust */ 2614 * robust */
2590 return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED); 2615 return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED);
2591} 2616}
2595/* load_object on it. I admit it is a highly inefficient way to make things, */ 2620/* load_object on it. I admit it is a highly inefficient way to make things, */
2596/* but it was simple to make and allows reusing the load_object function. */ 2621/* but it was simple to make and allows reusing the load_object function. */
2597/* Remember not to use load_object_str in a time-critical situation. */ 2622/* Remember not to use load_object_str in a time-critical situation. */
2598/* Also remember that multiparts objects are not supported for now. */ 2623/* Also remember that multiparts objects are not supported for now. */
2599 2624
2600object* load_object_str(char *obstr) 2625object* load_object_str(const char *obstr)
2601{ 2626{
2602 object *op; 2627 object *op;
2603 FILE *tempfile; 2628 FILE *tempfile;
2604 char filename[MAX_BUF]; 2629 char filename[MAX_BUF];
2605 sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir); 2630 sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir);
2629 2654
2630/* This returns the first object in who's inventory that 2655/* This returns the first object in who's inventory that
2631 * has the same type and subtype match. 2656 * has the same type and subtype match.
2632 * returns NULL if no match. 2657 * returns NULL if no match.
2633 */ 2658 */
2634object *find_obj_by_type_subtype(object *who, int type, int subtype) 2659object *find_obj_by_type_subtype(const object *who, int type, int subtype)
2635{ 2660{
2636 object *tmp; 2661 object *tmp;
2637 2662
2638 for (tmp=who->inv; tmp; tmp=tmp->below) 2663 for (tmp=who->inv; tmp; tmp=tmp->below)
2639 if (tmp->type == type && tmp->subtype == subtype) return tmp; 2664 if (tmp->type == type && tmp->subtype == subtype) return tmp;
2645 * otherwise return NULL. 2670 * otherwise return NULL.
2646 * 2671 *
2647 * key must be a passed in shared string - otherwise, this won't 2672 * key must be a passed in shared string - otherwise, this won't
2648 * do the desired thing. 2673 * do the desired thing.
2649 */ 2674 */
2650key_value * get_ob_key_link(object * ob, const char * key) { 2675key_value * get_ob_key_link(const object * ob, const char * key) {
2651 key_value * link; 2676 key_value * link;
2652 2677
2653 for (link = ob->key_values; link != NULL; link = link->next) { 2678 for (link = ob->key_values; link != NULL; link = link->next) {
2654 if (link->key == key) { 2679 if (link->key == key) {
2655 return link; 2680 return link;
2664 * 2689 *
2665 * The argument doesn't need to be a shared string. 2690 * The argument doesn't need to be a shared string.
2666 * 2691 *
2667 * The returned string is shared. 2692 * The returned string is shared.
2668 */ 2693 */
2669const char * get_ob_key_value(object * op, const char * const key) { 2694const char * get_ob_key_value(const object * op, const char * const key) {
2670 key_value * link; 2695 key_value * link;
2671 const char * canonical_key; 2696 const char * canonical_key;
2672 2697
2673 canonical_key = find_string(key); 2698 canonical_key = find_string(key);
2674 2699
2704 * Returns TRUE on success. 2729 * Returns TRUE on success.
2705 */ 2730 */
2706int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) { 2731int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) {
2707 key_value * field = NULL, *last=NULL; 2732 key_value * field = NULL, *last=NULL;
2708 2733
2709 LOG(llevDebug, "set_ob_value_s: '%s' '%s' %d\n", canonical_key, value, add_key);
2710
2711 for (field=op->key_values; field != NULL; field=field->next) { 2734 for (field=op->key_values; field != NULL; field=field->next) {
2712 if (field->key != canonical_key) { 2735 if (field->key != canonical_key) {
2713 last = field; 2736 last = field;
2714 continue; 2737 continue;
2715 } 2738 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines