ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/pets.C
(Generate patch)

Comparing deliantra/server/server/pets.C (file contents):
Revision 1.3 by root, Sun Sep 3 00:18:42 2006 UTC vs.
Revision 1.9 by root, Thu Sep 14 22:34:04 2006 UTC

1/*
2 * static char *rcsid_pets_c =
3 * "$Id: pets.C,v 1.3 2006/09/03 00:18:42 root Exp $";
4 */
5
6/* 1/*
7 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
8 3
9 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
21 16
22 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 20
26 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
27*/ 22*/
28 23
29#include <global.h> 24#include <global.h>
30#ifndef __CEXTRACT__ 25#ifndef __CEXTRACT__
31#include <sproto.h> 26# include <sproto.h>
32#endif 27#endif
33 28
34/* given that 'pet' is a friendly object, this function returns a 29/* given that 'pet' is a friendly object, this function returns a
35 * monster the pet should attack, NULL if nothing appropriate is 30 * monster the pet should attack, NULL if nothing appropriate is
36 * found. it basically looks for nasty things around the owner 31 * found. it basically looks for nasty things around the owner
37 * of the pet to attack. 32 * of the pet to attack.
38 * this is now tilemap aware. 33 * this is now tilemap aware.
39 */ 34 */
40 35
36object *
41object *get_pet_enemy(object * pet, rv_vector *rv){ 37get_pet_enemy (object *pet, rv_vector * rv)
38{
42 object *owner, *tmp, *attacker, *tmp3; 39 object *owner, *tmp, *attacker, *tmp3;
43 int i; 40 int i;
44 sint16 x,y; 41 sint16 x, y;
45 mapstruct *nm; 42 mapstruct *nm;
46 int search_arr[SIZEOFFREE]; 43 int search_arr[SIZEOFFREE];
47 int mflags; 44 int mflags;
48 45
49 attacker = pet->attacked_by; /*pointer to attacking enemy*/ 46 attacker = pet->attacked_by; /*pointer to attacking enemy */
50 pet->attacked_by = NULL; /*clear this, since we are dealing with it*/ 47 pet->attacked_by = NULL; /*clear this, since we are dealing with it */
51 48
52 if ((owner = get_owner(pet)) != NULL) { 49 if ((owner = get_owner (pet)) != NULL)
50 {
53 /* If the owner has turned on the pet, make the pet 51 /* If the owner has turned on the pet, make the pet
54 * unfriendly. 52 * unfriendly.
53 */
54 if ((check_enemy (owner, rv)) == pet)
55 {
56 CLEAR_FLAG (pet, FLAG_FRIENDLY);
57 remove_friendly_object (pet);
58 pet->attack_movement &= ~PETMOVE;
59 return owner;
60 }
61 }
62 else
63 {
64 /* else the owner is no longer around, so the
65 * pet no longer needs to be friendly.
66 */
67 CLEAR_FLAG (pet, FLAG_FRIENDLY);
68 remove_friendly_object (pet);
69 pet->attack_movement &= ~PETMOVE;
70 return NULL;
71 }
72 /* If they are not on the same map, the pet won't be agressive */
73 if (!on_same_map (pet, owner))
74 return NULL;
75
76 /* See if the pet has an existing enemy. If so, don't start a new one */
77 if ((tmp = check_enemy (pet, rv)) != NULL)
78 {
79 if (tmp == owner && !QUERY_FLAG (pet, FLAG_CONFUSED) && QUERY_FLAG (pet, FLAG_FRIENDLY))
80 /* without this check, you can actually get pets with
81 * enemy set to owner!
55 */ 82 */
56 if ((check_enemy(owner,rv)) == pet) { 83 pet->enemy = NULL;
57 CLEAR_FLAG(pet, FLAG_FRIENDLY); 84 else
58 remove_friendly_object(pet); 85 return tmp;
59 pet->attack_movement &=~PETMOVE; 86 }
60 return owner; 87 get_search_arr (search_arr);
88
89 if (owner->type == PLAYER && owner->contr->petmode > pet_normal)
90 {
91 if (owner->contr->petmode == pet_sad)
61 } 92 {
62 } else { 93 tmp = find_nearest_living_creature (pet);
63 /* else the owner is no longer around, so the 94 if (tmp != NULL)
64 * pet no longer needs to be friendly.
65 */ 95 {
66 CLEAR_FLAG(pet, FLAG_FRIENDLY); 96 get_rangevector (pet, tmp, rv, 0);
67 remove_friendly_object(pet); 97 if (check_enemy (pet, rv) != NULL)
68 pet->attack_movement &=~PETMOVE; 98 return tmp;
99 else
100 pet->enemy = NULL;
101 }
102 /* if we got here we have no enemy */
103 /* we return NULL to avoid heading back to the owner */
104 pet->enemy = NULL;
69 return NULL; 105 return NULL;
70 } 106 }
71 /* If they are not on the same map, the pet won't be agressive */
72 if (!on_same_map(pet,owner))
73 return NULL;
74
75 /* See if the pet has an existing enemy. If so, don't start a new one*/
76 if((tmp=check_enemy(pet, rv))!=NULL)
77 { 107 }
78 if(tmp == owner && !QUERY_FLAG(pet,FLAG_CONFUSED) 108
79 && QUERY_FLAG(pet,FLAG_FRIENDLY)) 109 /* Since the pet has no existing enemy, look for anything nasty
80 /* without this check, you can actually get pets with 110 * around the owner that it should go and attack.
81 * enemy set to owner! 111 */
112 tmp3 = NULL;
113 for (i = 0; i < SIZEOFFREE; i++)
114 {
115 x = owner->x + freearr_x[search_arr[i]];
116 y = owner->y + freearr_y[search_arr[i]];
117 nm = owner->map;
118 /* Only look on the space if there is something alive there. */
119 mflags = get_map_flags (nm, &nm, x, y, &x, &y);
120 if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE)
121 {
122 for (tmp = get_map_ob (nm, x, y); tmp != NULL; tmp = tmp->above)
82 */ 123 {
124 object *tmp2 = tmp->head == NULL ? tmp : tmp->head;
125
126 if (QUERY_FLAG (tmp2, FLAG_ALIVE) && ((!QUERY_FLAG (tmp2, FLAG_FRIENDLY) &&
127 (tmp2->type != PLAYER)) ||
128 should_arena_attack (pet, owner, tmp2))
129 && !QUERY_FLAG (tmp2, FLAG_UNAGGRESSIVE) && tmp2 != pet && tmp2 != owner && can_detect_enemy (pet, tmp2, rv))
130 {
131
132 if (!can_see_enemy (pet, tmp2))
133 {
134 if (tmp3 != NULL)
135 tmp3 = tmp2;
136 }
137 else
138 {
139 pet->enemy = tmp2;
140 if (check_enemy (pet, rv) != NULL)
141 return tmp2;
142 else
143 pet->enemy = NULL;
144 }
145 } /* if this is a valid enemy */
146 } /* for objects on this space */
147 } /* if there is something living on this space */
148 } /* for loop of spaces around the owner */
149
150 /* fine, we went through the whole loop and didn't find one we could
151 see, take what we have */
152 if (tmp3 != NULL)
153 {
154 pet->enemy = tmp3;
155 if (check_enemy (pet, rv) != NULL)
156 return tmp3;
157 else
158 pet->enemy = NULL;
159 }
160
161 /* No threat to owner, check to see if the pet has an attacker */
162 if (attacker)
163 {
164 /* also need to check to make sure it is not freindly */
165 /* or otherwise non-hostile, and is an appropriate target */
166 if (!QUERY_FLAG (attacker, FLAG_FRIENDLY) && on_same_map (pet, attacker))
167 {
168 pet->enemy = attacker;
169
170 if (check_enemy (pet, rv) != NULL)
171 return attacker;
172 else
83 pet->enemy = NULL; 173 pet->enemy = NULL;
84 else 174 }
85 return tmp;
86 } 175 }
87 get_search_arr(search_arr);
88 176
177 /* Don't have an attacker or legal enemy, so look for a new one!.
178 * This looks for one around where the pet is. Thus, you could lead
179 * a pet to danger, then take a few steps back. This code is basically
180 * the same as the code that looks around the owner.
181 */
89 if (owner->type == PLAYER && owner->contr->petmode > pet_normal) { 182 if (owner->type == PLAYER && owner->contr->petmode != pet_defend)
90 if (owner->contr->petmode == pet_sad) {
91 tmp = find_nearest_living_creature(pet);
92 if (tmp != NULL) {
93 get_rangevector(pet, tmp, rv, 0);
94 if(check_enemy(pet, rv) != NULL)
95 return tmp;
96 else
97 pet->enemy = NULL;
98 }
99 /* if we got here we have no enemy */
100 /* we return NULL to avoid heading back to the owner */
101 pet->enemy = NULL;
102 return NULL;
103 }
104 } 183 {
105
106 /* Since the pet has no existing enemy, look for anything nasty
107 * around the owner that it should go and attack.
108 */
109 tmp3 = NULL; 184 tmp3 = NULL;
110 for (i = 0; i < SIZEOFFREE; i++) { 185 for (i = 0; i < SIZEOFFREE; i++)
186 {
111 x = owner->x + freearr_x[search_arr[i]]; 187 x = pet->x + freearr_x[search_arr[i]];
112 y = owner->y + freearr_y[search_arr[i]]; 188 y = pet->y + freearr_y[search_arr[i]];
113 nm = owner->map; 189 nm = pet->map;
114 /* Only look on the space if there is something alive there. */ 190 /* Only look on the space if there is something alive there. */
115 mflags = get_map_flags(nm, &nm, x, y, &x, &y); 191 mflags = get_map_flags (nm, &nm, x, y, &x, &y);
116 if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE) { 192 if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE)
193 {
117 for (tmp = get_map_ob(nm, x, y); tmp != NULL; tmp = tmp->above) { 194 for (tmp = get_map_ob (nm, x, y); tmp != NULL; tmp = tmp->above)
195 {
118 object *tmp2 = tmp->head == NULL?tmp:tmp->head; 196 object *tmp2 = tmp->head == NULL ? tmp : tmp->head;
119 197
120 if (QUERY_FLAG(tmp2,FLAG_ALIVE) && (( 198 if (QUERY_FLAG (tmp2, FLAG_ALIVE) && ((!QUERY_FLAG (tmp2, FLAG_FRIENDLY) &&
121 !QUERY_FLAG(tmp2, FLAG_FRIENDLY) &&
122 (tmp2->type != PLAYER)) || 199 (tmp2->type != PLAYER)) ||
123 should_arena_attack(pet, owner, tmp2)) 200 should_arena_attack (pet, owner, tmp2))
124 && !QUERY_FLAG(tmp2,FLAG_UNAGGRESSIVE) && 201 && !QUERY_FLAG (tmp2, FLAG_UNAGGRESSIVE) && tmp2 != pet && tmp2 != owner && can_detect_enemy (pet, tmp2, rv))
125 tmp2 != pet && tmp2 != owner && 202 {
126 can_detect_enemy(pet, tmp2, rv)) {
127 203
128 if (!can_see_enemy(pet, tmp2)) { 204 if (!can_see_enemy (pet, tmp2))
205 {
129 if (tmp3 != NULL) 206 if (tmp3 != NULL)
130 tmp3 = tmp2; 207 tmp3 = tmp2;
131 } else {
132 pet->enemy = tmp2;
133 if(check_enemy(pet, rv)!=NULL)
134 return tmp2;
135 else
136 pet->enemy = NULL;
137 } 208 }
138 }/* if this is a valid enemy */ 209 else
210 {
211 pet->enemy = tmp2;
212 if (check_enemy (pet, rv) != NULL)
213 return tmp2;
214 else
215 pet->enemy = NULL;
216 }
217 } /* make sure we can get to the bugger */
139 }/* for objects on this space */ 218 } /* for objects on this space */
140 }/* if there is something living on this space */ 219 } /* if there is something living on this space */
141 } /* for loop of spaces around the owner */ 220 } /* for loop of spaces around the pet */
221 } /* pet in defence mode */
142 222
143 /* fine, we went through the whole loop and didn't find one we could 223 /* fine, we went through the whole loop and didn't find one we could
144 see, take what we have */ 224 see, take what we have */
145 if (tmp3 != NULL) { 225 if (tmp3 != NULL)
226 {
146 pet->enemy = tmp3; 227 pet->enemy = tmp3;
147 if (check_enemy(pet, rv) != NULL) 228 if (check_enemy (pet, rv) != NULL)
148 return tmp3; 229 return tmp3;
149 else 230 else
150 pet->enemy = NULL; 231 pet->enemy = NULL;
151 }
152
153 /* No threat to owner, check to see if the pet has an attacker*/
154 if (attacker)
155 { 232 }
156 /* need to be sure this is the right one! */
157 if (attacker->count == pet->attacked_by_count)
158 {
159 /* also need to check to make sure it is not freindly */
160 /* or otherwise non-hostile, and is an appropriate target */
161 if (!QUERY_FLAG(attacker, FLAG_FRIENDLY) && on_same_map(pet, attacker))
162 {
163 pet->enemy = attacker;
164 if (check_enemy(pet, rv) != NULL)
165 return attacker;
166 else
167 pet->enemy = NULL;
168 }
169 }
170 }
171 233
172 /* Don't have an attacker or legal enemy, so look for a new one!.
173 * This looks for one around where the pet is. Thus, you could lead
174 * a pet to danger, then take a few steps back. This code is basically
175 * the same as the code that looks around the owner.
176 */
177 if (owner->type == PLAYER && owner->contr->petmode != pet_defend) {
178 tmp3 = NULL;
179 for (i = 0; i < SIZEOFFREE; i++) {
180 x = pet->x + freearr_x[search_arr[i]];
181 y = pet->y + freearr_y[search_arr[i]];
182 nm = pet->map;
183 /* Only look on the space if there is something alive there. */
184 mflags = get_map_flags(nm, &nm, x,y, &x, &y);
185 if (!(mflags & P_OUT_OF_MAP) && mflags & P_IS_ALIVE) {
186 for (tmp = get_map_ob(nm, x, y); tmp != NULL; tmp = tmp->above) {
187 object *tmp2 = tmp->head == NULL?tmp:tmp->head;
188 if (QUERY_FLAG(tmp2,FLAG_ALIVE) && ((
189 !QUERY_FLAG(tmp2, FLAG_FRIENDLY) &&
190 (tmp2->type != PLAYER)) ||
191 should_arena_attack(pet, owner, tmp2))
192 && !QUERY_FLAG(tmp2,FLAG_UNAGGRESSIVE) &&
193 tmp2 != pet && tmp2 != owner &&
194 can_detect_enemy(pet, tmp2, rv)) {
195
196 if (!can_see_enemy(pet, tmp2)) {
197 if (tmp3 != NULL)
198 tmp3 = tmp2;
199 } else {
200 pet->enemy = tmp2;
201 if(check_enemy(pet, rv)!=NULL)
202 return tmp2;
203 else
204 pet->enemy = NULL;
205 }
206 } /* make sure we can get to the bugger */
207 }/* for objects on this space */
208 } /* if there is something living on this space */
209 } /* for loop of spaces around the pet */
210 } /* pet in defence mode */
211
212 /* fine, we went through the whole loop and didn't find one we could
213 see, take what we have */
214 if (tmp3 != NULL) {
215 pet->enemy = tmp3;
216 if (check_enemy(pet, rv) != NULL)
217 return tmp3;
218 else
219 pet->enemy = NULL;
220 }
221
222 /* Didn't find anything - return the owner's enemy or NULL */ 234 /* Didn't find anything - return the owner's enemy or NULL */
223 return check_enemy(pet, rv); 235 return check_enemy (pet, rv);
224} 236}
225 237
238void
226void terminate_all_pets(object *owner) { 239terminate_all_pets (object *owner)
240{
227 objectlink *obl, *next; 241 objectlink *obl, *next;
242
228 for(obl = first_friendly_object; obl != NULL; obl = next) { 243 for (obl = first_friendly_object; obl != NULL; obl = next)
244 {
229 object *ob = obl->ob; 245 object *ob = obl->ob;
246
230 next = obl->next; 247 next = obl->next;
231 if(get_owner(ob) == owner) { 248 if (get_owner (ob) == owner)
249 {
232 if(!QUERY_FLAG(ob, FLAG_REMOVED)) 250 if (!QUERY_FLAG (ob, FLAG_REMOVED))
233 remove_ob(ob); 251 remove_ob (ob);
234 remove_friendly_object(ob); 252 remove_friendly_object (ob);
235 free_object(ob); 253 free_object (ob);
236 } 254 }
237 } 255 }
238} 256}
239 257
240/* 258/*
241 * Unfortunately, sometimes, the owner of a pet is in the 259 * Unfortunately, sometimes, the owner of a pet is in the
242 * process of entering a new map when this is called. 260 * process of entering a new map when this is called.
244 * the pet... 262 * the pet...
245 * Interesting enough, we don't use the passed map structure in 263 * Interesting enough, we don't use the passed map structure in
246 * this function. 264 * this function.
247 */ 265 */
248 266
267void
249void remove_all_pets(mapstruct *map) { 268remove_all_pets (mapstruct *map)
269{
250 objectlink *obl, *next; 270 objectlink *obl, *next;
251 object *owner; 271 object *owner;
252 272
253 for(obl = first_friendly_object; obl != NULL; obl = next) { 273 for (obl = first_friendly_object; obl != NULL; obl = next)
274 {
254 next = obl->next; 275 next = obl->next;
255 if(obl->ob->type != PLAYER && QUERY_FLAG(obl->ob,FLAG_FRIENDLY) && 276 if (obl->ob->type != PLAYER && QUERY_FLAG (obl->ob, FLAG_FRIENDLY) &&
256 (owner = get_owner(obl->ob)) != NULL && !on_same_map(owner, obl->ob)) 277 (owner = get_owner (obl->ob)) != NULL && !on_same_map (owner, obl->ob))
257 { 278 {
258 /* follow owner checks map status for us */ 279 /* follow owner checks map status for us */
259 follow_owner(obl->ob,owner); 280 follow_owner (obl->ob, owner);
260 } 281 }
261 } 282 }
262} 283}
263 284
285int
264int follow_owner(object *ob, object *owner) { 286follow_owner (object *ob, object *owner)
287{
265 object *tmp; 288 object *tmp;
266 int dir; 289 int dir;
267 290
268 if (!QUERY_FLAG(ob,FLAG_REMOVED)) 291 if (!QUERY_FLAG (ob, FLAG_REMOVED))
269 remove_ob(ob); 292 remove_ob (ob);
270 293
271 if(owner->map == NULL) { 294 if (owner->map == NULL)
295 {
272 LOG(llevError,"Can't follow owner (%d): no map.\n", &owner->name); 296 LOG (llevError, "Can't follow owner (%d): no map.\n", &owner->name);
273 goto fail; 297 goto fail;
274 } 298 }
275 if(owner->map->in_memory != MAP_IN_MEMORY) { 299 if (owner->map->in_memory != MAP_IN_MEMORY)
300 {
276 LOG(llevError,"Owner of the pet not on a map in memory!?\n"); 301 LOG (llevError, "Owner of the pet not on a map in memory!?\n");
277 goto fail; 302 goto fail;
278 } 303 }
279 304
280 dir = find_free_spot(ob, owner->map, owner->x, owner->y, 1, SIZEOFFREE); 305 dir = find_free_spot (ob, owner->map, owner->x, owner->y, 1, SIZEOFFREE);
281 306
282 if (dir==-1) { 307 if (dir == -1)
308 {
283 LOG(llevMonster,"No space for pet to follow, freeing %s.\n", &ob->name); 309 LOG (llevMonster, "No space for pet to follow, freeing %s.\n", &ob->name);
284 goto fail; 310 goto fail;
285 } 311 }
286 for(tmp=ob;tmp!=NULL;tmp=tmp->more) { 312 for (tmp = ob; tmp != NULL; tmp = tmp->more)
313 {
287 tmp->x = owner->x + freearr_x[dir]+(tmp->arch==NULL?0:tmp->arch->clone.x); 314 tmp->x = owner->x + freearr_x[dir] + (tmp->arch == NULL ? 0 : tmp->arch->clone.x);
288 tmp->y = owner->y + freearr_y[dir]+(tmp->arch==NULL?0:tmp->arch->clone.y); 315 tmp->y = owner->y + freearr_y[dir] + (tmp->arch == NULL ? 0 : tmp->arch->clone.y);
289 tmp->map = owner->map; 316 tmp->map = owner->map;
290 if (OUT_OF_REAL_MAP(tmp->map, tmp->x, tmp->y)) { 317 if (OUT_OF_REAL_MAP (tmp->map, tmp->x, tmp->y))
318 {
291 tmp->map = get_map_from_coord(tmp->map, &tmp->x, &tmp->y); 319 tmp->map = get_map_from_coord (tmp->map, &tmp->x, &tmp->y);
292 } 320 }
293 } 321 }
294 insert_ob_in_map(ob, ob->map, NULL,0); 322 insert_ob_in_map (ob, ob->map, NULL, 0);
295 if (owner->type == PLAYER) /* Uh, I hope this is always true... */ 323 if (owner->type == PLAYER) /* Uh, I hope this is always true... */
296 new_draw_info(NDI_UNIQUE, 0,owner, "Your pet magically appears next to you"); 324 new_draw_info (NDI_UNIQUE, 0, owner, "Your pet magically appears next to you");
297 325
298 return 0; 326 return 0;
299 327
300fail: 328fail:
301 remove_friendly_object (ob); 329 remove_friendly_object (ob);
302 free_object (ob); 330 free_object (ob);
303 331
304 return 1; 332 return 1;
305} 333}
306 334
335void
307void pet_move(object * ob) 336pet_move (object *ob)
308{ 337{
309 int dir, tag, i; 338 int dir, tag, i;
310 sint16 dx, dy; 339 sint16 dx, dy;
311 object *ob2, *owner; 340 object *ob2, *owner;
312 mapstruct *m; 341 mapstruct *m;
313 342
314 /* Check to see if player pulled out */ 343 /* Check to see if player pulled out */
315 if ((owner = get_owner(ob)) == NULL) { 344 if ((owner = get_owner (ob)) == NULL)
345 {
316 remove_ob(ob); /* Will be freed when returning */ 346 remove_ob (ob); /* Will be freed when returning */
317 remove_friendly_object(ob); 347 remove_friendly_object (ob);
318 free_object(ob); 348 free_object (ob);
319 LOG(llevMonster, "Pet: no owner, leaving.\n"); 349 LOG (llevMonster, "Pet: no owner, leaving.\n");
350 return;
351 }
352
353 /* move monster into the owners map if not in the same map */
354 if (!on_same_map (ob, owner))
355 {
356 follow_owner (ob, owner);
357 return;
358 }
359 /* Calculate Direction */
360 if (owner->type == PLAYER && owner->contr->petmode == pet_sad)
361 {
362 /* in S&D mode, if we have no enemy, run randomly about. */
363 for (i = 0; i < 15; i++)
364 {
365 dir = rndm (1, 8);
366 dx = ob->x + freearr_x[dir];
367 dy = ob->y + freearr_y[dir];
368 m = ob->map;
369 if (get_map_flags (ob->map, &m, dx, dy, &dx, &dy) & P_OUT_OF_MAP)
370 continue;
371 else if (OB_TYPE_MOVE_BLOCK (ob, GET_MAP_MOVE_BLOCK (m, dx, dy)))
372 continue;
373 else
374 break;
375 }
376 }
377 else
378 {
379 struct rv_vector rv;
380
381 get_rangevector (ob, ob->owner, &rv, 0);
382 dir = rv.direction;
383 }
384 ob->direction = dir;
385
386 tag = ob->count;
387 /* move_ob returns 0 if the object couldn't move. If that is the
388 * case, lets do some other work.
389 */
390 if (!(move_ob (ob, dir, ob)))
391 {
392 object *part;
393
394 /* the failed move_ob above may destroy the pet, so check here */
395 if (was_destroyed (ob, tag))
320 return; 396 return;
321 }
322 397
323 /* move monster into the owners map if not in the same map */ 398 for (part = ob; part != NULL; part = part->more)
324 if (!on_same_map(ob, owner)) { 399 {
325 follow_owner(ob, owner);
326 return;
327 }
328 /* Calculate Direction */
329 if (owner->type == PLAYER && owner->contr->petmode == pet_sad) {
330 /* in S&D mode, if we have no enemy, run randomly about. */
331 for (i=0; i < 15; i++) {
332 dir = rndm(1, 8);
333 dx = ob->x + freearr_x[dir]; 400 dx = part->x + freearr_x[dir];
334 dy = ob->y + freearr_y[dir]; 401 dy = part->y + freearr_y[dir];
335 m = ob->map; 402 m = get_map_from_coord (part->map, &dx, &dy);
336 if (get_map_flags(ob->map, &m, dx, dy, &dx, &dy) & P_OUT_OF_MAP) 403 if (!m)
337 continue; 404 continue;
338 else if (OB_TYPE_MOVE_BLOCK(ob, GET_MAP_MOVE_BLOCK(m, dx, dy))) 405
339 continue; 406 for (ob2 = get_map_ob (m, dx, dy); ob2 != NULL; ob2 = ob2->above)
340 else 407 {
408 object *new_ob;
409
410 new_ob = ob2->head ? ob2->head : ob2;
411 if (new_ob == ob)
341 break; 412 break;
342 }
343 } else {
344 struct rv_vector rv;
345 get_rangevector (ob, ob->owner, &rv, 0);
346 dir = rv.direction;
347 }
348 ob->direction = dir;
349
350 tag = ob->count;
351 /* move_ob returns 0 if the object couldn't move. If that is the
352 * case, lets do some other work.
353 */
354 if (!(move_ob(ob, dir, ob))) {
355 object *part;
356
357 /* the failed move_ob above may destroy the pet, so check here */
358 if (was_destroyed(ob, tag)) return;
359
360 for(part = ob; part != NULL; part = part->more)
361 {
362 dx = part->x + freearr_x[dir];
363 dy = part->y + freearr_y[dir];
364 m = get_map_from_coord(part->map, &dx, &dy);
365 if (!m) continue;
366
367 for (ob2 = get_map_ob(m, dx, dy); ob2 != NULL; ob2 = ob2->above)
368 {
369 object *new_ob;
370 new_ob = ob2->head?ob2->head:ob2;
371 if(new_ob == ob)
372 break;
373 if (new_ob == ob->owner) 413 if (new_ob == ob->owner)
374 return; 414 return;
375 if (get_owner(new_ob) == ob->owner) 415 if (get_owner (new_ob) == ob->owner)
376 break; 416 break;
377 417
378 /* Hmm. Did we try to move into an enemy monster? If so, 418 /* Hmm. Did we try to move into an enemy monster? If so,
379 * make it our enemy. 419 * make it our enemy.
380 */ 420 */
381 if (QUERY_FLAG(new_ob,FLAG_ALIVE) && !QUERY_FLAG(ob,FLAG_UNAGGRESSIVE) 421 if (QUERY_FLAG (new_ob, FLAG_ALIVE) && !QUERY_FLAG (ob, FLAG_UNAGGRESSIVE)
382 && !QUERY_FLAG(new_ob,FLAG_UNAGGRESSIVE) && 422 && !QUERY_FLAG (new_ob, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (new_ob, FLAG_FRIENDLY))
383 !QUERY_FLAG(new_ob,FLAG_FRIENDLY)) { 423 {
384 424
385 ob->enemy = new_ob; 425 ob->enemy = new_ob;
386 if(new_ob->enemy == NULL) 426 if (new_ob->enemy == NULL)
387 new_ob->enemy = ob; 427 new_ob->enemy = ob;
388 return;
389 } else if (new_ob->type == PLAYER) {
390 new_draw_info(NDI_UNIQUE, 0,new_ob, "You stand in the way of someones pet.");
391 return; 428 return;
392 } 429 }
430 else if (new_ob->type == PLAYER)
431 {
432 new_draw_info (NDI_UNIQUE, 0, new_ob, "You stand in the way of someones pet.");
433 return;
393 } 434 }
394 } 435 }
436 }
395 /* Try a different course */ 437 /* Try a different course */
396 dir = absdir(dir + 4 - (RANDOM() %5) - (RANDOM()%5)); 438 dir = absdir (dir + 4 - (RANDOM () % 5) - (RANDOM () % 5));
397 (void) move_ob(ob, dir, ob); 439 (void) move_ob (ob, dir, ob);
398 } 440 }
399 return; 441 return;
400} 442}
401 443
402/**************************************************************************** 444/****************************************************************************
403 * 445 *
404 * GOLEM SPELL CODE 446 * GOLEM SPELL CODE
409 * proper for map insertion. 451 * proper for map insertion.
410 * at is the archetype, op is the caster of the spell, dir is the 452 * at is the archetype, op is the caster of the spell, dir is the
411 * direction the monster should be placed in. 453 * direction the monster should be placed in.
412 * is_golem is to note that this is a golem spell. 454 * is_golem is to note that this is a golem spell.
413 */ 455 */
456object *
414object *fix_summon_pet(archetype *at, object *op, int dir, int is_golem ) { 457fix_summon_pet (archetype *at, object *op, int dir, int is_golem)
458{
415 archetype *atmp; 459 archetype *atmp;
416 object *tmp=NULL, *prev=NULL, *head=NULL; 460 object *tmp = NULL, *prev = NULL, *head = NULL;
417 461
418 for(atmp = at; atmp!=NULL; atmp = atmp->more) { 462 for (atmp = at; atmp != NULL; atmp = atmp->more)
463 {
419 tmp = arch_to_object(atmp); 464 tmp = arch_to_object (atmp);
420 if (atmp == at) { 465 if (atmp == at)
466 {
421 if(!is_golem) 467 if (!is_golem)
422 SET_FLAG(tmp, FLAG_MONSTER); 468 SET_FLAG (tmp, FLAG_MONSTER);
423 set_owner(tmp, op); 469 set_owner (tmp, op);
424 if (op->type == PLAYER) { 470 if (op->type == PLAYER)
471 {
425 tmp->stats.exp = 0; 472 tmp->stats.exp = 0;
426 add_friendly_object(tmp); 473 add_friendly_object (tmp);
427 SET_FLAG(tmp, FLAG_FRIENDLY); 474 SET_FLAG (tmp, FLAG_FRIENDLY);
475 if (is_golem)
428 if(is_golem) CLEAR_FLAG(tmp, FLAG_MONSTER); 476 CLEAR_FLAG (tmp, FLAG_MONSTER);
477 }
429 } else { 478 else
479 {
430 if(QUERY_FLAG(op, FLAG_FRIENDLY)) { 480 if (QUERY_FLAG (op, FLAG_FRIENDLY))
481 {
431 object *owner = get_owner(op); 482 object *owner = get_owner (op);
483
484 if (owner != NULL)
432 if(owner != NULL) {/* For now, we transfer ownership */ 485 { /* For now, we transfer ownership */
433 set_owner(tmp,owner); 486 set_owner (tmp, owner);
434 tmp->attack_movement = PETMOVE; 487 tmp->attack_movement = PETMOVE;
435 add_friendly_object(tmp); 488 add_friendly_object (tmp);
436 SET_FLAG(tmp, FLAG_FRIENDLY); 489 SET_FLAG (tmp, FLAG_FRIENDLY);
437 } 490 }
438 } 491 }
439 } 492 }
440 if(op->type!=PLAYER || !is_golem) { 493 if (op->type != PLAYER || !is_golem)
494 {
441 tmp->attack_movement = PETMOVE; 495 tmp->attack_movement = PETMOVE;
442 tmp->speed_left = -1; 496 tmp->speed_left = -1;
443 tmp->type = 0; 497 tmp->type = 0;
444 tmp->enemy = op->enemy; 498 tmp->enemy = op->enemy;
499 }
445 } else 500 else
446 tmp->type = GOLEM; 501 tmp->type = GOLEM;
502
447 503 }
448 }
449 if(head == NULL) 504 if (head == NULL)
450 head = tmp; 505 head = tmp;
451 tmp->x = op->x + freearr_x[dir] + tmp->arch->clone.x; 506 tmp->x = op->x + freearr_x[dir] + tmp->arch->clone.x;
452 tmp->y = op->y + freearr_y[dir] + tmp->arch->clone.y; 507 tmp->y = op->y + freearr_y[dir] + tmp->arch->clone.y;
453 tmp->map = op->map; 508 tmp->map = op->map;
454 if(tmp->invisible) tmp->invisible=0; 509 if (tmp->invisible)
510 tmp->invisible = 0;
455 if(head != tmp) 511 if (head != tmp)
456 tmp->head = head, prev->more = tmp; 512 tmp->head = head, prev->more = tmp;
457 prev = tmp; 513 prev = tmp;
458 } 514 }
459 head->direction = dir; 515 head->direction = dir;
460 516
461 /* need to change some monster attr to prevent problems/crashing */ 517 /* need to change some monster attr to prevent problems/crashing */
462 head->last_heal=0; 518 head->last_heal = 0;
463 head->last_eat=0; 519 head->last_eat = 0;
464 head->last_grace=0; 520 head->last_grace = 0;
465 head->last_sp=0; 521 head->last_sp = 0;
466 head->other_arch=NULL; 522 head->other_arch = NULL;
467 head->stats.exp = 0; 523 head->stats.exp = 0;
468 CLEAR_FLAG(head,FLAG_CHANGING); 524 CLEAR_FLAG (head, FLAG_CHANGING);
469 CLEAR_FLAG(head,FLAG_STAND_STILL); 525 CLEAR_FLAG (head, FLAG_STAND_STILL);
470 CLEAR_FLAG(head,FLAG_GENERATOR); 526 CLEAR_FLAG (head, FLAG_GENERATOR);
471 CLEAR_FLAG(head,FLAG_SPLITTING); 527 CLEAR_FLAG (head, FLAG_SPLITTING);
472 if(head->attacktype&AT_GHOSTHIT) head->attacktype=(AT_PHYSICAL|AT_DRAIN); 528 if (head->attacktype & AT_GHOSTHIT)
529 head->attacktype = (AT_PHYSICAL | AT_DRAIN);
473 530
474 return head; 531 return head;
475} 532}
476 533
477/* updated this to allow more than the golem 'head' to attack */ 534/* updated this to allow more than the golem 'head' to attack */
535
478/* op is the golem to be moved. */ 536/* op is the golem to be moved. */
479 537
538void
480void move_golem(object *op) { 539move_golem (object *op)
540{
481 int made_attack=0; 541 int made_attack = 0;
482 object *tmp; 542 object *tmp;
483 tag_t tag; 543 tag_t tag;
484 544
485 if(QUERY_FLAG(op, FLAG_MONSTER)) 545 if (QUERY_FLAG (op, FLAG_MONSTER))
486 return; /* Has already been moved */ 546 return; /* Has already been moved */
487 547
488 if(get_owner(op)==NULL) { 548 if (get_owner (op) == NULL)
549 {
489 LOG(llevDebug,"Golem without owner destructed.\n"); 550 LOG (llevDebug, "Golem without owner destructed.\n");
490 remove_ob(op); 551 remove_ob (op);
491 free_object(op); 552 free_object (op);
492 return; 553 return;
493 } 554 }
494 /* It would be nice to have a cleaner way of what message to print 555 /* It would be nice to have a cleaner way of what message to print
495 * when the golem expires than these hard coded entries. 556 * when the golem expires than these hard coded entries.
496 * Note it is intentional that a golems duration is based on its 557 * Note it is intentional that a golems duration is based on its
497 * hp, and not duration 558 * hp, and not duration
498 */ 559 */
499 if(--op->stats.hp<0) { 560 if (--op->stats.hp < 0)
561 {
500 if (op->msg) 562 if (op->msg)
501 new_draw_info(NDI_UNIQUE, 0,op->owner,op->msg); 563 new_draw_info (NDI_UNIQUE, 0, op->owner, op->msg);
502 op->owner->contr->ranges[range_golem]=NULL; 564 op->owner->contr->ranges[range_golem] = NULL;
503 op->owner->contr->golem_count = 0; 565 op->owner->contr->golem_count = 0;
504 remove_friendly_object(op); 566 remove_friendly_object (op);
505 remove_ob(op); 567 remove_ob (op);
506 free_object(op); 568 free_object (op);
507 return; 569 return;
508 } 570 }
509 571
510 /* Do golem attacks/movement for single & multisq golems. 572 /* Do golem attacks/movement for single & multisq golems.
511 * Assuming here that op is the 'head' object. Pass only op to 573 * Assuming here that op is the 'head' object. Pass only op to
512 * move_ob (makes recursive calls to other parts) 574 * move_ob (makes recursive calls to other parts)
513 * move_ob returns 0 if the creature was not able to move. 575 * move_ob returns 0 if the creature was not able to move.
514 */ 576 */
515 tag = op->count; 577 tag = op->count;
516 if(move_ob(op,op->direction,op)) return; 578 if (move_ob (op, op->direction, op))
579 return;
517 if (was_destroyed (op, tag)) 580 if (was_destroyed (op, tag))
518 return; 581 return;
519 582
520 for(tmp=op;tmp;tmp=tmp->more) { 583 for (tmp = op; tmp; tmp = tmp->more)
584 {
521 sint16 x=tmp->x+freearr_x[op->direction],y=tmp->y+freearr_y[op->direction]; 585 sint16 x = tmp->x + freearr_x[op->direction], y = tmp->y + freearr_y[op->direction];
522 object *victim; 586 object *victim;
523 mapstruct *m; 587 mapstruct *m;
524 int mflags; 588 int mflags;
525 589
526 m = op->map; 590 m = op->map;
527 mflags = get_map_flags(m, &m, x, y, &x, &y); 591 mflags = get_map_flags (m, &m, x, y, &x, &y);
528 592
529 if (mflags & P_OUT_OF_MAP) continue; 593 if (mflags & P_OUT_OF_MAP)
594 continue;
530 595
531 for(victim=get_map_ob(op->map,x,y);victim;victim=victim->above) 596 for (victim = get_map_ob (op->map, x, y); victim; victim = victim->above)
532 if(QUERY_FLAG(victim,FLAG_ALIVE)) break; 597 if (QUERY_FLAG (victim, FLAG_ALIVE))
598 break;
533 599
534 /* We used to call will_hit_self to make sure we don't 600 /* We used to call will_hit_self to make sure we don't
535 * hit ourselves, but that didn't work, and I don't really 601 * hit ourselves, but that didn't work, and I don't really
536 * know if that was more efficient anyways than this. 602 * know if that was more efficient anyways than this.
537 * This at least works. Note that victim->head can be NULL, 603 * This at least works. Note that victim->head can be NULL,
538 * but since we are not trying to dereferance that pointer, 604 * but since we are not trying to dereferance that pointer,
539 * that isn't a problem. 605 * that isn't a problem.
540 */ 606 */
541 if(victim && victim!=op && victim->head!=op) { 607 if (victim && victim != op && victim->head != op)
608 {
542 609
543 /* for golems with race fields, we don't attack 610 /* for golems with race fields, we don't attack
544 * aligned races 611 * aligned races
545 */ 612 */
546 613
547 if(victim->race && op->race && strstr(op->race,victim->race)) { 614 if (victim->race && op->race && strstr (op->race, victim->race))
548 if(op->owner) new_draw_info_format(NDI_UNIQUE, 0,op->owner, 615 {
549 "%s avoids damaging %s.", &op->name, &victim->name); 616 if (op->owner)
617 new_draw_info_format (NDI_UNIQUE, 0, op->owner, "%s avoids damaging %s.", &op->name, &victim->name);
618 }
550 } else if (victim == op->owner) { 619 else if (victim == op->owner)
551 if(op->owner) new_draw_info_format(NDI_UNIQUE, 0,op->owner, 620 {
552 "%s avoids damaging you.", &op->name); 621 if (op->owner)
622 new_draw_info_format (NDI_UNIQUE, 0, op->owner, "%s avoids damaging you.", &op->name);
623 }
553 } else { 624 else
625 {
554 attack_ob(victim,op); 626 attack_ob (victim, op);
555 made_attack=1; 627 made_attack = 1;
556 } 628 }
557 } /* If victim */ 629 } /* If victim */
558 } 630 }
631 if (made_attack)
559 if(made_attack) update_object(op,UP_OBJ_FACE); 632 update_object (op, UP_OBJ_FACE);
560} 633}
561 634
562/* this is a really stupid function when you get down and 635/* this is a really stupid function when you get down and
563 * look at it. Keep it here for the time being - makes life 636 * look at it. Keep it here for the time being - makes life
564 * easier if we ever decide to do more interesting thing with 637 * easier if we ever decide to do more interesting thing with
565 * controlled golems. 638 * controlled golems.
566 */ 639 */
640void
567void control_golem(object *op,int dir) { 641control_golem (object *op, int dir)
642{
568 op->direction=dir; 643 op->direction = dir;
569} 644}
570 645
571/* summon golem: summons a monster for 'op'. caster is the object 646/* summon golem: summons a monster for 'op'. caster is the object
572 * casting the spell, dir is the direction to place the monster, 647 * casting the spell, dir is the direction to place the monster,
573 * at is the archetype of the monster, and spob is the spell 648 * at is the archetype of the monster, and spob is the spell
574 * object. At this stage, all spob is really used for is to 649 * object. At this stage, all spob is really used for is to
575 * adjust some values in the monster. 650 * adjust some values in the monster.
576 */ 651 */
652int
577int summon_golem(object *op,object *caster,int dir,object *spob) { 653summon_golem (object *op, object *caster, int dir, object *spob)
654{
578 object *tmp, *god=NULL; 655 object *tmp, *god = NULL;
579 archetype *at; 656 archetype *at;
580 char buf[MAX_BUF]; 657 char buf[MAX_BUF];
581 658
582 /* Because there can be different golem spells, player may want to 659 /* Because there can be different golem spells, player may want to
583 * 'lose' their old golem. 660 * 'lose' their old golem.
584 */ 661 */
585 if(op->type==PLAYER && 662 if (op->type == PLAYER && op->contr->ranges[range_golem] != NULL && op->contr->golem_count == op->contr->ranges[range_golem]->count)
586 op->contr->ranges[range_golem]!=NULL && 663 {
587 op->contr->golem_count == op->contr->ranges[range_golem]->count) {
588 new_draw_info(NDI_UNIQUE, 0, op, "You dismiss your existing golem."); 664 new_draw_info (NDI_UNIQUE, 0, op, "You dismiss your existing golem.");
589 remove_ob(op->contr->ranges[range_golem]); 665 remove_ob (op->contr->ranges[range_golem]);
590 free_object(op->contr->ranges[range_golem]); 666 free_object (op->contr->ranges[range_golem]);
591 op->contr->ranges[range_golem]=NULL; 667 op->contr->ranges[range_golem] = NULL;
592 op->contr->golem_count=(uint32)-1; 668 op->contr->golem_count = (uint32) - 1;
593 } 669 }
594 670
595 if (spob->other_arch) 671 if (spob->other_arch)
596 at = spob->other_arch; 672 at = spob->other_arch;
597 else if (spob->race) { 673 else if (spob->race)
674 {
598 god = find_god(determine_god(caster)); 675 god = find_god (determine_god (caster));
599 676
600 if (!god) { 677 if (!god)
678 {
601 new_draw_info_format(NDI_UNIQUE, 0,op,"You must worship a god to cast %s.", &spob->name); 679 new_draw_info_format (NDI_UNIQUE, 0, op, "You must worship a god to cast %s.", &spob->name);
602 return 0; 680 return 0;
603 } 681 }
682
604 at = determine_holy_arch (god, spob->race); 683 at = determine_holy_arch (god, spob->race);
684
605 if (!at) { 685 if (!at)
686 {
606 new_draw_info_format(NDI_UNIQUE, 0,op,"%s has no %s for you to call.", 687 new_draw_info_format (NDI_UNIQUE, 0, op, "%s has no %s for you to call.", &god->name, &spob->race);
607 &god->name, &spob->race);
608 return 0; 688 return 0;
609 } 689 }
610 } else { 690 }
691 else
692 {
611 LOG(llevError,"Spell %s lacks other_arch\n", &spob->name); 693 LOG (llevError, "Spell %s lacks other_arch\n", &spob->name);
612 return 0; 694 return 0;
613 } 695 }
614 696
615 if(!dir) 697 if (!dir)
616 dir=find_free_spot(NULL,op->map,op->x,op->y,1,SIZEOFFREE1+1); 698 dir = find_free_spot (NULL, op->map, op->x, op->y, 1, SIZEOFFREE1 + 1);
617 699
618 if ((dir==-1) || ob_blocked(&at->clone, op->map, op->x + freearr_x[dir], op->y + freearr_y[dir])) { 700 if (dir == -1 || ob_blocked (&at->clone, op->map, op->x + freearr_x[dir], op->y + freearr_y[dir]))
701 {
619 new_draw_info(NDI_UNIQUE, 0,op,"There is something in the way."); 702 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
620 return 0; 703 return 0;
621 } 704 }
622 /* basically want to get proper map/coordinates for this object */ 705 /* basically want to get proper map/coordinates for this object */
623 706
624 if(!(tmp=fix_summon_pet(at,op,dir,GOLEM))) { 707 if (!(tmp = fix_summon_pet (at, op, dir, GOLEM)))
708 {
625 new_draw_info(NDI_UNIQUE, 0,op,"Your spell fails."); 709 new_draw_info (NDI_UNIQUE, 0, op, "Your spell fails.");
626 return 0; 710 return 0;
627 } 711 }
628 712
629 if(op->type==PLAYER) { 713 if (op->type == PLAYER)
714 {
630 tmp->type=GOLEM; 715 tmp->type = GOLEM;
631 set_owner(tmp,op); 716 set_owner (tmp, op);
632 set_spell_skill(op, caster, spob, tmp); 717 set_spell_skill (op, caster, spob, tmp);
633 op->contr->ranges[range_golem]=tmp; 718 op->contr->ranges[range_golem] = tmp;
634 op->contr->golem_count = tmp->count; 719 op->contr->golem_count = tmp->count;
635 /* give the player control of the golem */ 720 /* give the player control of the golem */
636 op->contr->shoottype=range_golem; 721 op->contr->shoottype = range_golem;
637 } else { 722 }
723 else
724 {
638 if(QUERY_FLAG(op, FLAG_FRIENDLY)) { 725 if (QUERY_FLAG (op, FLAG_FRIENDLY))
726 {
639 object *owner = get_owner(op); 727 object *owner = get_owner (op);
640 if (owner != NULL) { /* For now, we transfer ownership */ 728
729 if (owner != NULL)
730 { /* For now, we transfer ownership */
641 set_owner (tmp, owner); 731 set_owner (tmp, owner);
642 tmp->attack_movement = PETMOVE; 732 tmp->attack_movement = PETMOVE;
643 add_friendly_object (tmp); 733 add_friendly_object (tmp);
644 SET_FLAG (tmp, FLAG_FRIENDLY); 734 SET_FLAG (tmp, FLAG_FRIENDLY);
645 }
646 } 735 }
736 }
737
647 SET_FLAG(tmp, FLAG_MONSTER); 738 SET_FLAG (tmp, FLAG_MONSTER);
648 } 739 }
649 740
650 /* make the speed positive.*/ 741 /* make the speed positive. */
651 tmp->speed = FABS(tmp->speed); 742 tmp->speed = FABS (tmp->speed);
652 743
653 /* This sets the level dependencies on dam and hp for monsters */ 744 /* This sets the level dependencies on dam and hp for monsters */
654 /* players can't cope with too strong summonings. */ 745 /* players can't cope with too strong summonings. */
655 /* but monsters can. reserve these for players. */ 746 /* but monsters can. reserve these for players. */
656 if(op->type==PLAYER) { 747 if (op->type == PLAYER)
657 tmp->stats.hp += spob->duration + 748 {
658 SP_level_duration_adjust(caster,spob); 749 tmp->stats.hp += spob->duration + SP_level_duration_adjust (caster, spob);
750
659 if (!spob->stats.dam) 751 if (!spob->stats.dam)
660 tmp->stats.dam += SP_level_dam_adjust(caster,spob); 752 tmp->stats.dam += SP_level_dam_adjust (caster, spob);
661 else 753 else
662 tmp->stats.dam= spob->stats.dam + 754 tmp->stats.dam = spob->stats.dam + SP_level_dam_adjust (caster, spob);
663 SP_level_dam_adjust(caster,spob); 755
664 tmp->speed += .02 * SP_level_range_adjust(caster,spob); 756 tmp->speed += .02 * SP_level_range_adjust (caster, spob);
665 tmp->speed = MIN(tmp->speed, 1.0); 757 tmp->speed = MIN (tmp->speed, 1.0);
758
759 if (spob->attacktype)
666 if (spob->attacktype) tmp->attacktype = spob->attacktype; 760 tmp->attacktype = spob->attacktype;
667 } 761 }
762
668 tmp->stats.wc -= SP_level_range_adjust(caster,spob); 763 tmp->stats.wc -= SP_level_range_adjust (caster, spob);
669 764
670 /* limit the speed to 0.3 for non-players, 1 for players. */ 765 /* limit the speed to 0.3 for non-players, 1 for players. */
671 766
672 /* make experience increase in proportion to the strength. 767 /* make experience increase in proportion to the strength.
673 * this is a bit simplistic - we are basically just looking at how 768 * this is a bit simplistic - we are basically just looking at how
674 * often the sp doubles and use that as the ratio. 769 * often the sp doubles and use that as the ratio.
675 */ 770 */
676 tmp->stats.exp *= 1 + (MAX(spob->stats.maxgrace, spob->stats.sp) / 771 tmp->stats.exp *= 1 + (MAX (spob->stats.maxgrace, spob->stats.sp) / caster_level (caster, spob));
677 caster_level(caster, spob));
678 tmp->speed_left= 0; 772 tmp->speed_left = 0;
679 tmp->direction=dir; 773 tmp->direction = dir;
680 774
681 /* Holy spell - some additional tailoring */ 775 /* Holy spell - some additional tailoring */
682 if (god) { 776 if (god)
777 {
683 object *tmp2; 778 object *tmp2;
684 779
685 sprintf(buf,"%s of %s", &spob->name, &god->name); 780 sprintf (buf, "%s of %s", &spob->name, &god->name);
686 buf[0] = toupper(buf[0]); 781 buf[0] = toupper (buf[0]);
687 782
688 for (tmp2=tmp; tmp2; tmp2=tmp2->more) 783 for (tmp2 = tmp; tmp2; tmp2 = tmp2->more)
689 tmp2->name = buf; 784 tmp2->name = buf;
690 785
691 tmp->attacktype |= god->attacktype; 786 tmp->attacktype |= god->attacktype;
692 memcpy(tmp->resist, god->resist, sizeof(tmp->resist)); 787 memcpy (tmp->resist, god->resist, sizeof (tmp->resist));
693 tmp->race = god->race; 788 tmp->race = god->race;
694 tmp->slaying = god->slaying; 789 tmp->slaying = god->slaying;
790
695 /* safety, we must allow a god's servants some reasonable attack */ 791 /* safety, we must allow a god's servants some reasonable attack */
696 if(!(tmp->attacktype&AT_PHYSICAL)) tmp->attacktype|=AT_PHYSICAL; 792 if (!(tmp->attacktype & AT_PHYSICAL))
793 tmp->attacktype |= AT_PHYSICAL;
697 } 794 }
698 795
699 insert_ob_in_map(tmp,tmp->map,op,0); 796 insert_ob_in_map (tmp, tmp->map, op, 0);
700 return 1; 797 return 1;
701} 798}
702 799
703 800
704/*************************************************************************** 801/***************************************************************************
705 * 802 *
711 * god) find acceptable. This checks level, races allowed by god, etc 808 * god) find acceptable. This checks level, races allowed by god, etc
712 * to determine what is acceptable. 809 * to determine what is acceptable.
713 * This returns NULL if no match was found. 810 * This returns NULL if no match was found.
714 */ 811 */
715 812
813object *
716object *choose_cult_monster(object *pl, object *god, int summon_level) { 814choose_cult_monster (object *pl, object *god, int summon_level)
815{
717 char buf[MAX_BUF]; 816 char buf[MAX_BUF];
718 const char *race; 817 const char *race;
719 int racenr, mon_nr,i; 818 int racenr, mon_nr, i;
720 racelink *list; 819 racelink *list;
721 objectlink *tobl; 820 objectlink *tobl;
722 object *otmp; 821 object *otmp;
723 822
724 /* Determine the number of races available */ 823 /* Determine the number of races available */
725 racenr=0; 824 racenr = 0;
726 strcpy(buf,god->race); 825 strcpy (buf, god->race);
727 race = strtok(buf,","); 826 race = strtok (buf, ",");
728 while(race) { 827 while (race)
828 {
729 racenr++; 829 racenr++;
730 race = strtok(NULL,","); 830 race = strtok (NULL, ",");
731 } 831 }
732 832
733 /* next, randomly select a race from the aligned_races string */ 833 /* next, randomly select a race from the aligned_races string */
734 if(racenr>1) { 834 if (racenr > 1)
835 {
735 racenr = rndm(0, racenr-1); 836 racenr = rndm (0, racenr - 1);
736 strcpy(buf,god->race); 837 strcpy (buf, god->race);
737 race = strtok(buf,","); 838 race = strtok (buf, ",");
738 for(i=0;i<racenr;i++) 839 for (i = 0; i < racenr; i++)
739 race = strtok(NULL,","); 840 race = strtok (NULL, ",");
740 } else 841 }
842 else
741 race = god->race; 843 race = god->race;
742 844
743 845
744 /* see if a we can match a race list of monsters. This should not 846 /* see if a we can match a race list of monsters. This should not
745 * happen, so graceful recovery isn't really needed, but this sanity 847 * happen, so graceful recovery isn't really needed, but this sanity
746 * checking is good for cases where the god archetypes mismatch the 848 * checking is good for cases where the god archetypes mismatch the
747 * race file 849 * race file
748 */ 850 */
749 if((list=find_racelink(race))==NULL) { 851 if ((list = find_racelink (race)) == NULL)
750 new_draw_info_format(NDI_UNIQUE, 0,pl, 852 {
751 "The spell fails! %s's creatures are beyond the range of your summons", 853 new_draw_info_format (NDI_UNIQUE, 0, pl, "The spell fails! %s's creatures are beyond the range of your summons", &god->name);
752 &god->name);
753 LOG(llevDebug,"choose_cult_monster() requested non-existent aligned race!\n"); 854 LOG (llevDebug, "choose_cult_monster() requested non-existent aligned race!\n");
754 return 0; 855 return 0;
755 } 856 }
756 857
757 /* search for an apprplritate monster on this race list */ 858 /* search for an apprplritate monster on this race list */
758 mon_nr=0; 859 mon_nr = 0;
759 for(tobl=list->member;tobl;tobl=tobl->next) { 860 for (tobl = list->member; tobl; tobl = tobl->next)
861 {
760 otmp=tobl->ob; 862 otmp = tobl->ob;
761 if(!otmp||!QUERY_FLAG(otmp,FLAG_MONSTER)) continue; 863 if (!otmp || !QUERY_FLAG (otmp, FLAG_MONSTER))
864 continue;
762 if(otmp->level<=summon_level) mon_nr++; 865 if (otmp->level <= summon_level)
866 mon_nr++;
763 } 867 }
764 868
765 /* If this god has multiple race entries, we should really choose another. 869 /* If this god has multiple race entries, we should really choose another.
766 * But then we either need to track which ones we have tried, or just 870 * But then we either need to track which ones we have tried, or just
767 * make so many calls to this function, and if we get so many without 871 * make so many calls to this function, and if we get so many without
768 * a valid entry, assuming nothing is available and quit. 872 * a valid entry, assuming nothing is available and quit.
769 */ 873 */
770 if (!mon_nr) return NULL; 874 if (!mon_nr)
771
772 mon_nr = rndm(0, mon_nr-1);
773 for(tobl=list->member;tobl;tobl=tobl->next) {
774 otmp=tobl->ob;
775 if(!otmp||!QUERY_FLAG(otmp,FLAG_MONSTER)) continue;
776 if(otmp->level<=summon_level && !mon_nr--) return otmp;
777 }
778 /* This should not happen */
779 LOG(llevDebug,"choose_cult_monster() mon_nr was set, but did not find a monster\n");
780 return NULL; 875 return NULL;
781}
782 876
877 mon_nr = rndm (0, mon_nr - 1);
878 for (tobl = list->member; tobl; tobl = tobl->next)
879 {
880 otmp = tobl->ob;
881 if (!otmp || !QUERY_FLAG (otmp, FLAG_MONSTER))
882 continue;
883 if (otmp->level <= summon_level && !mon_nr--)
884 return otmp;
885 }
886 /* This should not happen */
887 LOG (llevDebug, "choose_cult_monster() mon_nr was set, but did not find a monster\n");
888 return NULL;
889}
783 890
784 891int
785int summon_object(object *op, object *caster, object *spell_ob, int dir, const char *stringarg) 892summon_object (object *op, object *caster, object *spell_ob, int dir, const char *stringarg)
786{ 893{
787 sint16 x,y, nrof=1, i; 894 sint16 x, y, nrof = 1, i;
788 archetype *summon_arch; 895 archetype *summon_arch;
789 int ndir; 896 int ndir;
790 897
791 if (spell_ob->other_arch) { 898 if (spell_ob->other_arch)
792 summon_arch = spell_ob->other_arch; 899 summon_arch = spell_ob->other_arch;
793 } else if (spell_ob->randomitems) { 900 else if (spell_ob->randomitems)
901 {
794 int level = caster_level(caster, spell_ob); 902 int level = caster_level (caster, spell_ob);
795 treasure *tr, *lasttr=NULL;; 903 treasure *tr, *lasttr = NULL;
796 904
905 shstr_cmp sparam (stringarg);
906
797 /* In old code, this was a very convuluted for statement, 907 /* In old code, this was a very convoluted for statement,
798 * with all the checks in the 'for' portion itself. Much 908 * with all the checks in the 'for' portion itself. Much
799 * more readable to break some of the conditions out. 909 * more readable to break some of the conditions out.
800 */ 910 */
801 for (tr=spell_ob->randomitems->items; tr; tr=tr->next) { 911 for (tr = spell_ob->randomitems->items; tr; tr = tr->next)
912 {
802 if (level < tr->magic) break; 913 if (level < tr->magic)
914 break;
915
803 lasttr = tr; 916 lasttr = tr;
804 if(stringarg && !strcmp(tr->item->name,stringarg)) break; 917
918 if (tr->item->name == sparam)
919 break;
920
805 if (tr->next == NULL || tr->next->item == NULL) break; 921 if (!tr->next || !tr->next->item)
922 break;
806 } 923 }
924
807 if (!lasttr) { 925 if (!lasttr)
926 {
808 LOG(llevError,"Treasurelist %s did not generate a valid entry in summon_object\n", 927 LOG (llevError, "Treasurelist %s did not generate a valid entry in summon_object\n", &spell_ob->randomitems->name);
809 &spell_ob->randomitems->name);
810 new_draw_info(NDI_UNIQUE, 0, op, "The spell fails to summon any monsters."); 928 new_draw_info (NDI_UNIQUE, 0, op, "The spell fails to summon any monsters.");
811 return 0; 929 return 0;
812 } 930 }
931
813 summon_arch = lasttr->item; 932 summon_arch = lasttr->item;
814 nrof = lasttr->nrof; 933 nrof = lasttr->nrof;
815 934 }
816 } else if (spell_ob->race && !strcmp(spell_ob->race,"GODCULTMON")) { 935 else if (spell_ob->race && !strcmp (spell_ob->race, "GODCULTMON"))
936 {
817 object *god=find_god(determine_god(op)), *mon, *owner; 937 object *god = find_god (determine_god (op)), *mon, *owner;
818 int summon_level, tries; 938 int summon_level, tries;
819 939
820 if (!god && ((owner=get_owner(op))!=NULL)) { 940 if (!god && ((owner = get_owner (op)) != NULL))
821 god = find_god(determine_god(owner)); 941 god = find_god (determine_god (owner));
822 } 942
823 /* If we can't find a god, can't get what monster to summon */ 943 /* If we can't find a god, can't get what monster to summon */
944 if (!god)
824 if (!god) return 0; 945 return 0;
825 946
826 if (!god->race) { 947 if (!god->race)
827 new_draw_info_format(NDI_UNIQUE, 0,op, 948 {
828 "%s has no creatures that you may summon!", &god->name); 949 new_draw_info_format (NDI_UNIQUE, 0, op, "%s has no creatures that you may summon!", &god->name);
829 return 0; 950 return 0;
830 } 951 }
952
831 /* the summon level */ 953 /* the summon level */
832 summon_level=caster_level(caster, spell_ob); 954 summon_level = caster_level (caster, spell_ob);
833 if (summon_level==0) summon_level=1; 955 if (summon_level == 0)
956 summon_level = 1;
957
834 tries = 0; 958 tries = 0;
959 do
835 do { 960 {
836 mon = choose_cult_monster(op, god,summon_level); 961 mon = choose_cult_monster (op, god, summon_level);
837 if (!mon) { 962 if (!mon)
838 new_draw_info_format(NDI_UNIQUE, 0,op, 963 {
839 "%s fails to send anything.", &god->name); 964 new_draw_info_format (NDI_UNIQUE, 0, op, "%s fails to send anything.", &god->name);
840 return 0; 965 return 0;
841 } 966 }
967
842 ndir = dir; 968 ndir = dir;
969
843 if (!ndir) 970 if (!ndir)
844 ndir = find_free_spot(mon, op->map, op->x, op->y, 1, SIZEOFFREE); 971 ndir = find_free_spot (mon, op->map, op->x, op->y, 1, SIZEOFFREE);
972
845 if (ndir == -1 || ob_blocked(mon,op->map, op->x + freearr_x[ndir], op->y+freearr_y[ndir])) { 973 if (ndir == -1 || ob_blocked (mon, op->map, op->x + freearr_x[ndir], op->y + freearr_y[ndir]))
974 {
846 ndir=-1; 975 ndir = -1;
847 if (++tries == 5) { 976 if (++tries == 5)
977 {
848 new_draw_info(NDI_UNIQUE, 0,op, "There is something in the way."); 978 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
849 return 0; 979 return 0;
850 } 980 }
851 } 981 }
982 }
852 } while (ndir == -1); 983 while (ndir == -1);
984
853 if (mon->level > (summon_level/2)) 985 if (mon->level > (summon_level / 2))
854 nrof = random_roll(1, 2, op, PREFER_HIGH); 986 nrof = random_roll (1, 2, op, PREFER_HIGH);
855 else 987 else
856 nrof = die_roll(2, 2, op, PREFER_HIGH); 988 nrof = die_roll (2, 2, op, PREFER_HIGH);
989
857 summon_arch = mon->arch; 990 summon_arch = mon->arch;
858 } else { 991 }
992 else
859 summon_arch = NULL; 993 summon_arch = 0;
860 }
861 994
862 if (spell_ob->stats.dam) 995 if (spell_ob->stats.dam)
863 nrof += spell_ob->stats.dam + SP_level_dam_adjust(caster, spell_ob); 996 nrof += spell_ob->stats.dam + SP_level_dam_adjust (caster, spell_ob);
864 997
865 if (!summon_arch) { 998 if (!summon_arch)
999 {
866 new_draw_info(NDI_UNIQUE, 0, op, "There is no monsters available for summoning."); 1000 new_draw_info (NDI_UNIQUE, 0, op, "There is no monsters available for summoning.");
867 return 0; 1001 return 0;
868 } 1002 }
869 1003
870 for (i=1; i <= nrof; i++) { 1004 for (i = 1; i <= nrof; i++)
1005 {
871 archetype *atmp; 1006 archetype *atmp;
872 object *prev=NULL, *head=NULL, *tmp; 1007 object *prev = NULL, *head = NULL, *tmp;
873 1008
874 if (dir) { 1009 if (dir)
1010 {
875 ndir = dir; 1011 ndir = dir;
876 dir = absdir (dir+1); 1012 dir = absdir (dir + 1);
1013 }
877 } else 1014 else
878 ndir = find_free_spot(&summon_arch->clone, op->map, op->x, op->y, 1, SIZEOFFREE); 1015 ndir = find_free_spot (&summon_arch->clone, op->map, op->x, op->y, 1, SIZEOFFREE);
879 1016
880 if (ndir > 0) { 1017 if (ndir > 0)
1018 {
881 x = freearr_x[ndir]; 1019 x = freearr_x[ndir];
882 y = freearr_y[ndir]; 1020 y = freearr_y[ndir];
883 } 1021 }
884 1022
885 if (ndir == -1 || ob_blocked(&summon_arch->clone, op->map, op->x + x, op->y + y)){ 1023 if (ndir == -1 || ob_blocked (&summon_arch->clone, op->map, op->x + x, op->y + y))
1024 {
886 new_draw_info(NDI_UNIQUE, 0, op, "There is something in the way."); 1025 new_draw_info (NDI_UNIQUE, 0, op, "There is something in the way.");
887 if (nrof > 1) 1026 if (nrof > 1)
888 new_draw_info(NDI_UNIQUE, 0,op, "No more pets for this casting."); 1027 new_draw_info (NDI_UNIQUE, 0, op, "No more pets for this casting.");
889 1028
890 return nrof > 1; 1029 return nrof > 1;
891 } 1030 }
892 1031
893 for (atmp = summon_arch; atmp!=NULL; atmp=atmp->more) { 1032 for (atmp = summon_arch; atmp != NULL; atmp = atmp->more)
1033 {
894 tmp = arch_to_object(atmp); 1034 tmp = arch_to_object (atmp);
895 if (atmp == summon_arch) { 1035 if (atmp == summon_arch)
1036 {
896 if (QUERY_FLAG(tmp, FLAG_MONSTER)) { 1037 if (QUERY_FLAG (tmp, FLAG_MONSTER))
1038 {
897 set_owner(tmp, op); 1039 set_owner (tmp, op);
898 set_spell_skill(op, caster, spell_ob, tmp); 1040 set_spell_skill (op, caster, spell_ob, tmp);
899 tmp->enemy = op->enemy; 1041 tmp->enemy = op->enemy;
900 tmp->type = 0; 1042 tmp->type = 0;
901 CLEAR_FLAG(tmp, FLAG_SLEEP); 1043 CLEAR_FLAG (tmp, FLAG_SLEEP);
1044
902 if (op->type == PLAYER || QUERY_FLAG(op, FLAG_FRIENDLY)) { 1045 if (op->type == PLAYER || QUERY_FLAG (op, FLAG_FRIENDLY))
1046 {
903 /* If this is not set, we make it friendly */ 1047 /* If this is not set, we make it friendly */
904 if (!QUERY_FLAG(spell_ob, FLAG_MONSTER)) { 1048 if (!QUERY_FLAG (spell_ob, FLAG_MONSTER))
1049 {
905 SET_FLAG(tmp, FLAG_FRIENDLY); 1050 SET_FLAG (tmp, FLAG_FRIENDLY);
906 add_friendly_object(tmp); 1051 add_friendly_object (tmp);
907 tmp->stats.exp = 0; 1052 tmp->stats.exp = 0;
1053
908 if (spell_ob->attack_movement) 1054 if (spell_ob->attack_movement)
909 tmp->attack_movement = spell_ob->attack_movement; 1055 tmp->attack_movement = spell_ob->attack_movement;
1056
910 if (get_owner(op)) 1057 if (get_owner (op))
911 set_owner(tmp, get_owner(op)); 1058 set_owner (tmp, get_owner (op));
912 } 1059 }
913 } 1060 }
914 } 1061 }
1062
915 if (tmp->speed > MIN_ACTIVE_SPEED) tmp->speed_left = -1; 1063 if (tmp->speed > MIN_ACTIVE_SPEED)
1064 tmp->speed_left = -1;
1065 }
1066
1067 if (head == NULL)
1068 head = tmp;
1069 else
916 } 1070 {
917 if (head == NULL) head = tmp;
918 else {
919 tmp->head = head; 1071 tmp->head = head;
920 prev->more = tmp; 1072 prev->more = tmp;
921 } 1073 }
1074
922 prev = tmp; 1075 prev = tmp;
923 tmp->x = op->x + x + tmp->arch->clone.x; 1076 tmp->x = op->x + x + tmp->arch->clone.x;
924 tmp->y = op->y + y + tmp->arch->clone.y; 1077 tmp->y = op->y + y + tmp->arch->clone.y;
925 tmp->map = op->map; 1078 tmp->map = op->map;
926 } 1079 }
1080
927 head->direction = freedir[ndir]; 1081 head->direction = freedir[ndir];
928 head->stats.exp = 0; 1082 head->stats.exp = 0;
929 head = insert_ob_in_map(head, head->map, op, 0); 1083 head = insert_ob_in_map (head, head->map, op, 0);
1084
930 if (head && head->randomitems) { 1085 if (head && head->randomitems)
1086 {
931 object *tmp; 1087 object *tmp;
1088
932 create_treasure(head->randomitems, head, GT_APPLY | GT_STARTEQUIP, 6, 0); 1089 create_treasure (head->randomitems, head, GT_APPLY | GT_STARTEQUIP, 6, 0);
933 for (tmp=head->inv; tmp; tmp=tmp->below) 1090 for (tmp = head->inv; tmp; tmp = tmp->below)
1091 if (!tmp->nrof)
934 if (!tmp->nrof) SET_FLAG(tmp, FLAG_NO_DROP); 1092 SET_FLAG (tmp, FLAG_NO_DROP);
935 } 1093 }
936 } /* for i < nrof */ 1094 } /* for i < nrof */
1095
937 return 1; 1096 return 1;
938} 1097}
939 1098
940/* recursively look through the owner property of objects until the real owner 1099/* recursively look through the owner property of objects until the real owner
941is found */ 1100is found */
1101object *
942object *get_real_owner(object *ob) { 1102get_real_owner (object *ob)
1103{
943 object *realowner = ob; 1104 object *realowner = ob;
944 1105
945 if (realowner == NULL) return NULL; 1106 if (realowner == NULL)
946 1107 return NULL;
1108
947 while(get_owner(realowner) != NULL) 1109 while (get_owner (realowner) != NULL)
948 { 1110 {
949 realowner = get_owner(realowner); 1111 realowner = get_owner (realowner);
950 } 1112 }
951 return realowner; 1113 return realowner;
952} 1114}
953 1115
954/* determines if checks so pets don't attack players or other pets should be 1116/* determines if checks so pets don't attack players or other pets should be
955overruled by the arena petmode */ 1117overruled by the arena petmode */
1118int
956int should_arena_attack(object *pet,object *owner,object *target) { 1119should_arena_attack (object *pet, object *owner, object *target)
1120{
957 object *rowner, *towner; 1121 object *rowner, *towner;
958 1122
959 /* exit if the target, pet, or owner is null. */ 1123 /* exit if the target, pet, or owner is null. */
960 if ((target == NULL) || (pet == NULL) || (owner == NULL)) return 0; 1124 if ((target == NULL) || (pet == NULL) || (owner == NULL))
961 1125 return 0;
1126
962 /* get the owners of itself and the target, this is to deal with pets of 1127 /* get the owners of itself and the target, this is to deal with pets of
963 pets */ 1128 pets */
964 rowner = get_real_owner(owner); 1129 rowner = get_real_owner (owner);
965 if (target->type != PLAYER) { 1130 if (target->type != PLAYER)
1131 {
966 towner = get_real_owner(target); 1132 towner = get_real_owner (target);
967 } else { 1133 }
1134 else
1135 {
968 towner = 0; 1136 towner = 0;
969 } 1137 }
970 1138
971 /* if the pet has now owner, exit with error */ 1139 /* if the pet has now owner, exit with error */
972 if (rowner == NULL) { 1140 if (rowner == NULL)
1141 {
973 LOG(llevError,"Pet has no owner.\n"); 1142 LOG (llevError, "Pet has no owner.\n");
974 return 0; 1143 return 0;
975 } 1144 }
976 1145
977 /* if the target is not a player, and has no owner, we shouldn't be here 1146 /* if the target is not a player, and has no owner, we shouldn't be here
978 */ 1147 */
979 if ((towner == NULL) && (target->type != PLAYER)) { 1148 if ((towner == NULL) && (target->type != PLAYER))
1149 {
980 LOG(llevError,"Target is not a player but has no owner. We should not be here.\n"); 1150 LOG (llevError, "Target is not a player but has no owner. We should not be here.\n");
981 return 0; 1151 return 0;
982 } 1152 }
983 1153
984 /* make sure that the owner is a player */ 1154 /* make sure that the owner is a player */
985 if (rowner->type != PLAYER) return 0; 1155 if (rowner->type != PLAYER)
986 1156 return 0;
1157
987 /* abort if the petmode is not arena */ 1158 /* abort if the petmode is not arena */
988 if (rowner->contr->petmode != pet_arena) return 0; 1159 if (rowner->contr->petmode != pet_arena)
989 1160 return 0;
1161
990 /* abort if the pet, it's owner, or the target is not on battleground*/ 1162 /* abort if the pet, it's owner, or the target is not on battleground */
991 if (!(op_on_battleground(pet, NULL, NULL) && 1163 if (!(op_on_battleground (pet, NULL, NULL) && op_on_battleground (owner, NULL, NULL) && op_on_battleground (target, NULL, NULL)))
992 op_on_battleground(owner, NULL, NULL) && 1164 return 0;
993 op_on_battleground(target, NULL, NULL))) 1165
1166 /* if the target is a monster, make sure it's owner is not the same */
1167 if ((target->type != PLAYER) && (rowner == towner))
1168 return 0;
1169
1170 /* check if the target is a player which affects how it will handle
1171 parties */
1172 if (target->type != PLAYER)
1173 {
1174 /* if the target is owned by a player make sure than make sure
1175 it's not in the same party */
1176 if ((towner->type == PLAYER) && (rowner->contr->party != NULL))
1177 {
1178 if (rowner->contr->party == towner->contr->party)
994 return 0; 1179 return 0;
995 1180 }
996 /* if the target is a monster, make sure it's owner is not the same */ 1181 }
997 if ((target->type != PLAYER) && (rowner == towner)) return 0; 1182 else
998 1183 {
999 /* check if the target is a player which affects how it will handle
1000 parties */
1001 if (target->type != PLAYER) {
1002 /* if the target is owned by a player make sure than make sure
1003 it's not in the same party */
1004 if ((towner->type == PLAYER) && (rowner->contr->party != NULL)) {
1005 if (rowner->contr->party == towner->contr->party) return 0;
1006 }
1007 } else {
1008 /* if the target is a player make sure than make sure it's not 1184 /* if the target is a player make sure than make sure it's not
1009 in the same party */ 1185 in the same party */
1010 if (rowner->contr->party != NULL){ 1186 if (rowner->contr->party != NULL)
1011 if (rowner->contr->party == target->contr->party) return 0;
1012 }
1013 }
1014 1187 {
1188 if (rowner->contr->party == target->contr->party)
1015 return 1; 1189 return 0;
1190 }
1191 }
1192
1193 return 1;
1016} 1194}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines