1 | /* |
1 | /* |
2 | * static char *rcsid_object_c = |
2 | * static char *rcsid_object_c = |
3 | * "$Id: object.C,v 1.15 2006/09/04 13:55:54 root Exp $"; |
3 | * "$Id: object.C,v 1.16 2006/09/04 16:46:32 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 | |
… | |
… | |
111 | * |
111 | * |
112 | * Improvements made with merge: Better checking on potion, and also |
112 | * Improvements made with merge: Better checking on potion, and also |
113 | * check weight |
113 | * check weight |
114 | */ |
114 | */ |
115 | |
115 | |
116 | int CAN_MERGE(object *ob1, object *ob2) { |
116 | bool |
117 | |
117 | object::can_merge (object *ob1, object *ob2) |
|
|
118 | { |
118 | /* A couple quicksanity checks */ |
119 | /* A couple quicksanity checks */ |
119 | if ((ob1 == ob2) || (ob1->type != ob2->type)) return 0; |
120 | if ((ob1 == ob2) || (ob1->type != ob2->type)) |
120 | |
|
|
121 | if (ob1->speed != ob2->speed) return 0; |
|
|
122 | /* Note sure why the following is the case - either the object has to |
|
|
123 | * be animated or have a very low speed. Is this an attempted monster |
|
|
124 | * check? |
|
|
125 | */ |
|
|
126 | if (!QUERY_FLAG(ob1,FLAG_ANIMATE) && FABS((ob1)->speed) > MIN_ACTIVE_SPEED) |
|
|
127 | return 0; |
121 | return 0; |
128 | |
122 | |
|
|
123 | if (ob1->speed != ob2->speed) |
|
|
124 | return 0; |
|
|
125 | |
129 | /* Do not merge objects if nrof would overflow. We use 1UL<<31 since that |
126 | /* Do not merge objects if nrof would overflow. We use 1UL<<31 since that |
130 | * value could not be stored in a sint32 (which unfortunately sometimes is |
127 | * value could not be stored in a sint32 (which unfortunately sometimes is |
131 | * used to store nrof). |
128 | * used to store nrof). |
132 | */ |
129 | */ |
133 | if (ob1->nrof+ob2->nrof >= 1UL<<31) |
130 | if (ob1->nrof + ob2->nrof >= 1UL << 31) |
134 | return 0; |
131 | return 0; |
135 | |
132 | |
|
|
133 | /* If the objects have been identified, set the BEEN_APPLIED flag. |
|
|
134 | * This is to the comparison of the flags below will be OK. We |
|
|
135 | * just can't ignore the been applied or identified flags, as they |
|
|
136 | * are not equal - just if it has been identified, the been_applied |
|
|
137 | * flags lose any meaning. |
|
|
138 | */ |
|
|
139 | if (QUERY_FLAG (ob1, FLAG_IDENTIFIED)) |
|
|
140 | SET_FLAG (ob1, FLAG_BEEN_APPLIED); |
|
|
141 | |
|
|
142 | if (QUERY_FLAG (ob2, FLAG_IDENTIFIED)) |
|
|
143 | SET_FLAG (ob2, FLAG_BEEN_APPLIED); |
|
|
144 | |
|
|
145 | |
|
|
146 | /* the 0x400000 on flags2 is FLAG_INV_LOCK. I don't think something |
|
|
147 | * being locked in inventory should prevent merging. |
|
|
148 | * 0x4 in flags3 is CLIENT_SENT |
|
|
149 | */ |
|
|
150 | if ((ob1->arch != ob2->arch) || |
|
|
151 | (ob1->flags[0] != ob2->flags[0]) || |
|
|
152 | (ob1->flags[1] != ob2->flags[1]) || |
|
|
153 | ((ob1->flags[2] & ~0x400000) != (ob2->flags[2] & ~0x400000)) || |
|
|
154 | ((ob1->flags[3] & ~0x4) != (ob2->flags[3] & ~0x4)) || |
|
|
155 | (ob1->name != ob2->name) || |
|
|
156 | (ob1->title != ob2->title) || |
|
|
157 | (ob1->msg != ob2->msg) || |
|
|
158 | (ob1->weight != ob2->weight) || |
|
|
159 | (memcmp (&ob1->resist, &ob2->resist, sizeof (ob1->resist)) != 0) || |
|
|
160 | (memcmp (&ob1->stats, &ob2->stats, sizeof (ob1->stats)) != 0) || |
|
|
161 | (ob1->attacktype != ob2->attacktype) || |
|
|
162 | (ob1->magic != ob2->magic) || |
|
|
163 | (ob1->slaying != ob2->slaying) || |
|
|
164 | (ob1->skill != ob2->skill) || |
|
|
165 | (ob1->value != ob2->value) || |
|
|
166 | (ob1->animation_id != ob2->animation_id) || |
|
|
167 | (ob1->client_type != ob2->client_type) || |
|
|
168 | (ob1->materialname != ob2->materialname) || |
|
|
169 | (ob1->lore != ob2->lore) || |
|
|
170 | (ob1->subtype != ob2->subtype) || |
|
|
171 | (ob1->move_type != ob2->move_type) || |
|
|
172 | (ob1->move_block != ob2->move_block) || |
|
|
173 | (ob1->move_allow != ob2->move_allow) || |
|
|
174 | (ob1->move_on != ob2->move_on) || |
|
|
175 | (ob1->move_off != ob2->move_off) || |
|
|
176 | (ob1->move_slow != ob2->move_slow) || |
|
|
177 | (ob1->move_slow_penalty != ob2->move_slow_penalty)) |
|
|
178 | return 0; |
|
|
179 | |
136 | /* This is really a spellbook check - really, we should |
180 | /* This is really a spellbook check - really, we should |
137 | * check all objects in the inventory. |
181 | * check all objects in the inventory. |
138 | */ |
182 | */ |
139 | if (ob1->inv || ob2->inv) { |
183 | if (ob1->inv || ob2->inv) |
|
|
184 | { |
140 | /* if one object has inventory but the other doesn't, not equiv */ |
185 | /* if one object has inventory but the other doesn't, not equiv */ |
141 | if ((ob1->inv && !ob2->inv) || (ob2->inv && !ob1->inv)) return 0; |
186 | if ((ob1->inv && !ob2->inv) || (ob2->inv && !ob1->inv)) |
|
|
187 | return 0; |
142 | |
188 | |
143 | /* Now check to see if the two inventory objects could merge */ |
189 | /* Now check to see if the two inventory objects could merge */ |
144 | if (!CAN_MERGE(ob1->inv, ob2->inv)) return 0; |
190 | if (!CAN_MERGE (ob1->inv, ob2->inv)) |
|
|
191 | return 0; |
145 | |
192 | |
146 | /* inventory ok - still need to check rest of this object to see |
193 | /* inventory ok - still need to check rest of this object to see |
147 | * if it is valid. |
194 | * if it is valid. |
148 | */ |
195 | */ |
149 | } |
196 | } |
150 | |
197 | |
151 | /* If the objects have been identified, set the BEEN_APPLIED flag. |
|
|
152 | * This is to the comparison of the flags below will be OK. We |
|
|
153 | * just can't ignore the been applied or identified flags, as they |
|
|
154 | * are not equal - just if it has been identified, the been_applied |
|
|
155 | * flags lose any meaning. |
|
|
156 | */ |
|
|
157 | if (QUERY_FLAG(ob1, FLAG_IDENTIFIED)) |
|
|
158 | SET_FLAG(ob1, FLAG_BEEN_APPLIED); |
|
|
159 | |
|
|
160 | if (QUERY_FLAG(ob2, FLAG_IDENTIFIED)) |
|
|
161 | SET_FLAG(ob2, FLAG_BEEN_APPLIED); |
|
|
162 | |
|
|
163 | |
|
|
164 | /* the 0x400000 on flags2 is FLAG_INV_LOCK. I don't think something |
|
|
165 | * being locked in inventory should prevent merging. |
|
|
166 | * 0x4 in flags3 is CLIENT_SENT |
|
|
167 | */ |
|
|
168 | if ((ob1->arch != ob2->arch) || |
|
|
169 | (ob1->flags[0] != ob2->flags[0]) || |
|
|
170 | (ob1->flags[1] != ob2->flags[1]) || |
|
|
171 | ((ob1->flags[2] & ~0x400000) != (ob2->flags[2] & ~ 0x400000)) || |
|
|
172 | ((ob1->flags[3] & ~0x4) != (ob2->flags[3] & ~0x4)) || |
|
|
173 | (ob1->name != ob2->name) || |
|
|
174 | (ob1->title != ob2->title) || |
|
|
175 | (ob1->msg != ob2->msg) || |
|
|
176 | (ob1->weight != ob2->weight) || |
|
|
177 | (memcmp(&ob1->resist, &ob2->resist, sizeof(ob1->resist))!=0) || |
|
|
178 | (memcmp(&ob1->stats, &ob2->stats, sizeof(ob1->stats))!=0) || |
|
|
179 | (ob1->attacktype != ob2->attacktype) || |
|
|
180 | (ob1->magic != ob2->magic) || |
|
|
181 | (ob1->slaying != ob2->slaying) || |
|
|
182 | (ob1->skill != ob2->skill) || |
|
|
183 | (ob1->value != ob2->value) || |
|
|
184 | (ob1->animation_id != ob2->animation_id) || |
|
|
185 | (ob1->client_type != ob2->client_type) || |
|
|
186 | (ob1->materialname != ob2->materialname) || |
|
|
187 | (ob1->lore != ob2->lore) || |
|
|
188 | (ob1->subtype != ob2->subtype) || |
|
|
189 | (ob1->move_type != ob2->move_type) || |
|
|
190 | (ob1->move_block != ob2->move_block) || |
|
|
191 | (ob1->move_allow != ob2->move_allow) || |
|
|
192 | (ob1->move_on != ob2->move_on) || |
|
|
193 | (ob1->move_off != ob2->move_off) || |
|
|
194 | (ob1->move_slow != ob2->move_slow) || |
|
|
195 | (ob1->move_slow_penalty != ob2->move_slow_penalty) |
|
|
196 | ) |
|
|
197 | return 0; |
|
|
198 | |
|
|
199 | /* Don't merge objects that are applied. With the new 'body' code, |
198 | /* Don't merge objects that are applied. With the new 'body' code, |
200 | * it is possible for most any character to have more than one of |
199 | * it is possible for most any character to have more than one of |
201 | * some items equipped, and we don't want those to merge. |
200 | * some items equipped, and we don't want those to merge. |
202 | */ |
201 | */ |
203 | if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED)) |
202 | if (QUERY_FLAG (ob1, FLAG_APPLIED) || QUERY_FLAG (ob2, FLAG_APPLIED)) |
204 | return 0; |
203 | return 0; |
205 | |
204 | |
|
|
205 | /* Note sure why the following is the case - either the object has to |
|
|
206 | * be animated or have a very low speed. Is this an attempted monster |
|
|
207 | * check? |
|
|
208 | */ |
|
|
209 | if (!QUERY_FLAG (ob1, FLAG_ANIMATE) |
|
|
210 | && FABS ((ob1)->speed) > MIN_ACTIVE_SPEED) |
|
|
211 | return 0; |
|
|
212 | |
206 | switch (ob1->type) { |
213 | switch (ob1->type) |
|
|
214 | { |
207 | case SCROLL: |
215 | case SCROLL: |
208 | if (ob1->level != ob2->level) return 0; |
216 | if (ob1->level != ob2->level) |
|
|
217 | return 0; |
209 | break; |
218 | break; |
210 | |
|
|
211 | } |
219 | } |
|
|
220 | |
212 | if (ob1->key_values != NULL || ob2->key_values != NULL) { |
221 | if (ob1->key_values != NULL || ob2->key_values != NULL) |
|
|
222 | { |
213 | /* At least one of these has key_values. */ |
223 | /* At least one of these has key_values. */ |
214 | if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) { |
224 | if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) |
215 | /* One has fields, but the other one doesn't. */ |
225 | /* One has fields, but the other one doesn't. */ |
216 | return 0; |
226 | return 0; |
217 | } else if (!compare_ob_value_lists(ob1, ob2)) { |
227 | else if (!compare_ob_value_lists (ob1, ob2)) |
218 | return 0; |
228 | return 0; |
219 | } |
229 | } |
|
|
230 | |
|
|
231 | //TODO: generate an event or call into perl for additional checks |
|
|
232 | if (ob1->self || ob2->self) |
220 | } |
233 | { |
|
|
234 | ob1->optimise (); |
|
|
235 | ob2->optimise (); |
221 | |
236 | |
|
|
237 | if (ob1->self || ob2->self) |
|
|
238 | return 0; |
|
|
239 | } |
|
|
240 | |
222 | /* Everything passes, must be OK. */ |
241 | /* Everything passes, must be OK. */ |
223 | return 1; |
242 | return 1; |
224 | } |
243 | } |
225 | |
|
|
226 | /* |
244 | /* |
227 | * sum_weight() is a recursive function which calculates the weight |
245 | * sum_weight() is a recursive function which calculates the weight |
228 | * an object is carrying. It goes through in figures out how much |
246 | * an object is carrying. It goes through in figures out how much |
229 | * containers are carrying, and sums it up. |
247 | * containers are carrying, and sums it up. |
230 | */ |
248 | */ |