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.6 2006/06/04 19:46:55 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 | |
… | |
… | |
52 | |
52 | |
53 | object *objects; /* Pointer to the list of used objects */ |
53 | object *objects; /* Pointer to the list of used objects */ |
54 | object *free_objects; /* Pointer to the list of unused objects */ |
54 | object *free_objects; /* Pointer to the list of unused objects */ |
55 | object *active_objects; /* List of active objects that need to be processed */ |
55 | object *active_objects; /* List of active objects that need to be processed */ |
56 | |
56 | |
|
|
57 | void (*object_free_callback)(object *ob); |
57 | |
58 | |
58 | short freearr_x[SIZEOFFREE]= |
59 | short 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}; |
61 | short freearr_y[SIZEOFFREE]= |
62 | short 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. */ |
73 | static int compare_ob_value_lists_one(object * wants, object * has) { |
74 | static 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. */ |
107 | static int compare_ob_value_lists(object * ob1, object * ob2) { |
108 | static 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 | |
389 | object *get_nearest_part(object *op,object *pl) { |
391 | object *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 | |
418 | object *find_object_name(char *str) { |
420 | object *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. |
… | |
… | |
1060 | void free_object(object *ob) { |
1066 | void free_object(object *ob) { |
1061 | free_object2(ob, 0); |
1067 | free_object2(ob, 0); |
1062 | } |
1068 | } |
1063 | void free_object2(object *ob, int free_inventory) { |
1069 | void 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)) |
… | |
… | |
1702 | |
1718 | |
1703 | /* this function inserts an object in the map, but if it |
1719 | /* 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. |
1720 | * 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. |
1721 | * op is the object to insert it under: supplies x and the map. |
1706 | */ |
1722 | */ |
1707 | void replace_insert_ob_in_map(char *arch_string, object *op) { |
1723 | void replace_insert_ob_in_map(const char *arch_string, object *op) { |
1708 | object *tmp; |
1724 | object *tmp; |
1709 | object *tmp1; |
1725 | object *tmp1; |
1710 | |
1726 | |
1711 | /* first search for itself and remove any old instances */ |
1727 | /* first search for itself and remove any old instances */ |
1712 | |
1728 | |
… | |
… | |
2080 | * present_arch(arch, map, x, y) searches for any objects with |
2096 | * present_arch(arch, map, x, y) searches for any objects with |
2081 | * a matching archetype at the given map and coordinates. |
2097 | * a matching archetype at the given map and coordinates. |
2082 | * The first matching object is returned, or NULL if none. |
2098 | * The first matching object is returned, or NULL if none. |
2083 | */ |
2099 | */ |
2084 | |
2100 | |
2085 | object *present_arch(archetype *at, mapstruct *m, int x, int y) { |
2101 | object *present_arch(const archetype *at, mapstruct *m, int x, int y) { |
2086 | object *tmp; |
2102 | object *tmp; |
2087 | if(m==NULL || out_of_map(m,x,y)) { |
2103 | if(m==NULL || out_of_map(m,x,y)) { |
2088 | LOG(llevError,"Present_arch called outside map.\n"); |
2104 | LOG(llevError,"Present_arch called outside map.\n"); |
2089 | return NULL; |
2105 | return NULL; |
2090 | } |
2106 | } |
… | |
… | |
2116 | * present_in_ob(type, object) searches for any objects with |
2132 | * present_in_ob(type, object) searches for any objects with |
2117 | * a matching type variable in the inventory of the given object. |
2133 | * a matching type variable in the inventory of the given object. |
2118 | * The first matching object is returned, or NULL if none. |
2134 | * The first matching object is returned, or NULL if none. |
2119 | */ |
2135 | */ |
2120 | |
2136 | |
2121 | object *present_in_ob(unsigned char type,object *op) { |
2137 | object *present_in_ob(unsigned char type, const object *op) { |
2122 | object *tmp; |
2138 | object *tmp; |
2123 | for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) |
2139 | for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) |
2124 | if(tmp->type==type) |
2140 | if(tmp->type==type) |
2125 | return tmp; |
2141 | return tmp; |
2126 | return NULL; |
2142 | return NULL; |
… | |
… | |
2139 | * the object name, not the archetype name. this is so that the |
2155 | * 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 |
2156 | * spell code can use one object type (force), but change it's name |
2141 | * to be unique. |
2157 | * to be unique. |
2142 | */ |
2158 | */ |
2143 | |
2159 | |
2144 | object *present_in_ob_by_name(int type, char *str,object *op) { |
2160 | object *present_in_ob_by_name(int type, const char *str, const object *op) { |
2145 | object *tmp; |
2161 | object *tmp; |
2146 | |
2162 | |
2147 | for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) { |
2163 | for(tmp=op->inv; tmp!=NULL; tmp=tmp->below) { |
2148 | if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name))) |
2164 | if ((type==-1 || tmp->type==type) && (!strcmp(str, tmp->name))) |
2149 | return tmp; |
2165 | return tmp; |
… | |
… | |
2155 | * present_arch_in_ob(archetype, object) searches for any objects with |
2171 | * present_arch_in_ob(archetype, object) searches for any objects with |
2156 | * a matching archetype in the inventory of the given object. |
2172 | * a matching archetype in the inventory of the given object. |
2157 | * The first matching object is returned, or NULL if none. |
2173 | * The first matching object is returned, or NULL if none. |
2158 | */ |
2174 | */ |
2159 | |
2175 | |
2160 | object *present_arch_in_ob(archetype *at, object *op) { |
2176 | object *present_arch_in_ob(const archetype *at, const object *op) { |
2161 | object *tmp; |
2177 | object *tmp; |
2162 | for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) |
2178 | for(tmp=op->inv;tmp!=NULL;tmp=tmp->below) |
2163 | if( tmp->arch == at) |
2179 | if( tmp->arch == at) |
2164 | return tmp; |
2180 | return tmp; |
2165 | return NULL; |
2181 | return NULL; |
… | |
… | |
2219 | * to know if the space in question will block the object. We can't use |
2235 | * 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 |
2236 | * the archetype because that isn't correct if the monster has been |
2221 | * customized, changed states, etc. |
2237 | * customized, changed states, etc. |
2222 | */ |
2238 | */ |
2223 | |
2239 | |
2224 | int find_free_spot(object *ob, mapstruct *m,int x,int y,int start,int stop) { |
2240 | int find_free_spot(const object *ob, mapstruct *m,int x,int y,int start,int stop) { |
2225 | int i,index=0, flag; |
2241 | int i,index=0, flag; |
2226 | static int altern[SIZEOFFREE]; |
2242 | static int altern[SIZEOFFREE]; |
2227 | |
2243 | |
2228 | for(i=start;i<stop;i++) { |
2244 | for(i=start;i<stop;i++) { |
2229 | flag = ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i]); |
2245 | 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. |
2266 | * find_free_spot(), but it will search max number of squares. |
2251 | * But it will return the first available spot, not a random choice. |
2267 | * 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. |
2268 | * Changed 0.93.2: Have it return -1 if there is no free spot available. |
2253 | */ |
2269 | */ |
2254 | |
2270 | |
2255 | int find_first_free_spot(object *ob, mapstruct *m,int x,int y) { |
2271 | int find_first_free_spot(const object *ob, mapstruct *m,int x,int y) { |
2256 | int i; |
2272 | int i; |
2257 | for(i=0;i<SIZEOFFREE;i++) { |
2273 | for(i=0;i<SIZEOFFREE;i++) { |
2258 | if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i])) |
2274 | if(!ob_blocked(ob,m,x+freearr_x[i],y+freearr_y[i])) |
2259 | return i; |
2275 | return i; |
2260 | } |
2276 | } |
… | |
… | |
2361 | /* |
2377 | /* |
2362 | * distance(object 1, object 2) will return the square of the |
2378 | * distance(object 1, object 2) will return the square of the |
2363 | * distance between the two given objects. |
2379 | * distance between the two given objects. |
2364 | */ |
2380 | */ |
2365 | |
2381 | |
2366 | int distance(object *ob1,object *ob2) { |
2382 | int distance(const object *ob1, const object *ob2) { |
2367 | int i; |
2383 | int i; |
2368 | i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+ |
2384 | i= (ob1->x - ob2->x)*(ob1->x - ob2->x)+ |
2369 | (ob1->y - ob2->y)*(ob1->y - ob2->y); |
2385 | (ob1->y - ob2->y)*(ob1->y - ob2->y); |
2370 | return i; |
2386 | return i; |
2371 | } |
2387 | } |
… | |
… | |
2536 | * core dumps if they do. |
2552 | * core dumps if they do. |
2537 | * |
2553 | * |
2538 | * Add a check so we can't pick up invisible objects (0.93.8) |
2554 | * Add a check so we can't pick up invisible objects (0.93.8) |
2539 | */ |
2555 | */ |
2540 | |
2556 | |
2541 | int can_pick(object *who,object *item) { |
2557 | int can_pick(const object *who, const object *item) { |
2542 | return /*QUERY_FLAG(who,FLAG_WIZ)||*/ |
2558 | return /*QUERY_FLAG(who,FLAG_WIZ)||*/ |
2543 | (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&& |
2559 | (item->weight>0&&!QUERY_FLAG(item,FLAG_NO_PICK)&& |
2544 | !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible && |
2560 | !QUERY_FLAG(item,FLAG_ALIVE)&&!item->invisible && |
2545 | (who->type==PLAYER||item->weight<who->weight/3)); |
2561 | (who->type==PLAYER||item->weight<who->weight/3)); |
2546 | } |
2562 | } |
… | |
… | |
2581 | |
2597 | |
2582 | return dst; |
2598 | return dst; |
2583 | } |
2599 | } |
2584 | |
2600 | |
2585 | /* return true if the object was destroyed, 0 otherwise */ |
2601 | /* return true if the object was destroyed, 0 otherwise */ |
2586 | int was_destroyed (object *op, tag_t old_tag) |
2602 | int was_destroyed (const object *op, tag_t old_tag) |
2587 | { |
2603 | { |
2588 | /* checking for FLAG_FREED isn't necessary, but makes this function more |
2604 | /* checking for FLAG_FREED isn't necessary, but makes this function more |
2589 | * robust */ |
2605 | * robust */ |
2590 | return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED); |
2606 | return op->count != old_tag || QUERY_FLAG (op, FLAG_FREED); |
2591 | } |
2607 | } |
… | |
… | |
2595 | /* load_object on it. I admit it is a highly inefficient way to make things, */ |
2611 | /* 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. */ |
2612 | /* 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. */ |
2613 | /* Remember not to use load_object_str in a time-critical situation. */ |
2598 | /* Also remember that multiparts objects are not supported for now. */ |
2614 | /* Also remember that multiparts objects are not supported for now. */ |
2599 | |
2615 | |
2600 | object* load_object_str(char *obstr) |
2616 | object* load_object_str(const char *obstr) |
2601 | { |
2617 | { |
2602 | object *op; |
2618 | object *op; |
2603 | FILE *tempfile; |
2619 | FILE *tempfile; |
2604 | char filename[MAX_BUF]; |
2620 | char filename[MAX_BUF]; |
2605 | sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir); |
2621 | sprintf(filename,"%s/cfloadobstr2044",settings.tmpdir); |
… | |
… | |
2629 | |
2645 | |
2630 | /* This returns the first object in who's inventory that |
2646 | /* This returns the first object in who's inventory that |
2631 | * has the same type and subtype match. |
2647 | * has the same type and subtype match. |
2632 | * returns NULL if no match. |
2648 | * returns NULL if no match. |
2633 | */ |
2649 | */ |
2634 | object *find_obj_by_type_subtype(object *who, int type, int subtype) |
2650 | object *find_obj_by_type_subtype(const object *who, int type, int subtype) |
2635 | { |
2651 | { |
2636 | object *tmp; |
2652 | object *tmp; |
2637 | |
2653 | |
2638 | for (tmp=who->inv; tmp; tmp=tmp->below) |
2654 | for (tmp=who->inv; tmp; tmp=tmp->below) |
2639 | if (tmp->type == type && tmp->subtype == subtype) return tmp; |
2655 | if (tmp->type == type && tmp->subtype == subtype) return tmp; |
… | |
… | |
2645 | * otherwise return NULL. |
2661 | * otherwise return NULL. |
2646 | * |
2662 | * |
2647 | * key must be a passed in shared string - otherwise, this won't |
2663 | * key must be a passed in shared string - otherwise, this won't |
2648 | * do the desired thing. |
2664 | * do the desired thing. |
2649 | */ |
2665 | */ |
2650 | key_value * get_ob_key_link(object * ob, const char * key) { |
2666 | key_value * get_ob_key_link(const object * ob, const char * key) { |
2651 | key_value * link; |
2667 | key_value * link; |
2652 | |
2668 | |
2653 | for (link = ob->key_values; link != NULL; link = link->next) { |
2669 | for (link = ob->key_values; link != NULL; link = link->next) { |
2654 | if (link->key == key) { |
2670 | if (link->key == key) { |
2655 | return link; |
2671 | return link; |
… | |
… | |
2664 | * |
2680 | * |
2665 | * The argument doesn't need to be a shared string. |
2681 | * The argument doesn't need to be a shared string. |
2666 | * |
2682 | * |
2667 | * The returned string is shared. |
2683 | * The returned string is shared. |
2668 | */ |
2684 | */ |
2669 | const char * get_ob_key_value(object * op, const char * const key) { |
2685 | const char * get_ob_key_value(const object * op, const char * const key) { |
2670 | key_value * link; |
2686 | key_value * link; |
2671 | const char * canonical_key; |
2687 | const char * canonical_key; |
2672 | |
2688 | |
2673 | canonical_key = find_string(key); |
2689 | canonical_key = find_string(key); |
2674 | |
2690 | |
… | |
… | |
2704 | * Returns TRUE on success. |
2720 | * Returns TRUE on success. |
2705 | */ |
2721 | */ |
2706 | int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) { |
2722 | int set_ob_key_value_s(object * op, const char * canonical_key, const char * value, int add_key) { |
2707 | key_value * field = NULL, *last=NULL; |
2723 | key_value * field = NULL, *last=NULL; |
2708 | |
2724 | |
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) { |
2725 | for (field=op->key_values; field != NULL; field=field->next) { |
2712 | if (field->key != canonical_key) { |
2726 | if (field->key != canonical_key) { |
2713 | last = field; |
2727 | last = field; |
2714 | continue; |
2728 | continue; |
2715 | } |
2729 | } |