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

Comparing deliantra/server/server/move.C (file contents):
Revision 1.6 by root, Sun Sep 3 00:18:42 2006 UTC vs.
Revision 1.9 by root, Sat Sep 16 22:24:13 2006 UTC

1/*
2 * static char *rcsid_move_c =
3 * "$Id: move.C,v 1.6 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 author can be reached via e-mail to crossfire-devel@real-time.com 21 The author can be reached via e-mail to <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#ifdef COZY_SERVER 29#ifdef COZY_SERVER
35// use a ptotoype 30// use a ptotoype
36extern int same_party (partylist *a, partylist *b); 31extern int same_party (partylist *a, partylist *b);
42 * otherwise 1. 37 * otherwise 1.
43 * This is an improvement from the previous move_ob(), which 38 * This is an improvement from the previous move_ob(), which
44 * removed and inserted objects even if they were unable to move. 39 * removed and inserted objects even if they were unable to move.
45 */ 40 */
46 41
42int
47int move_object(object *op, int dir) { 43move_object (object *op, int dir)
44{
48 return move_ob(op, dir, op); 45 return move_ob (op, dir, op);
49} 46}
50 47
51 48
52/* object op is trying to move in direction dir. 49/* object op is trying to move in direction dir.
53 * originator is typically the same as op, but 50 * originator is typically the same as op, but
56 * returns 0 if the object is not able to move to the 53 * returns 0 if the object is not able to move to the
57 * desired space, 1 otherwise (in which case we also 54 * desired space, 1 otherwise (in which case we also
58 * move the object accordingly. This function is 55 * move the object accordingly. This function is
59 * very similiar to move_object. 56 * very similiar to move_object.
60 */ 57 */
58int
61int move_ob (object *op, int dir, object *originator) 59move_ob (object *op, int dir, object *originator)
62{ 60{
63 sint16 newx = op->x+freearr_x[dir]; 61 sint16 newx = op->x + freearr_x[dir];
64 sint16 newy = op->y+freearr_y[dir]; 62 sint16 newy = op->y + freearr_y[dir];
65 object *tmp; 63 object *tmp;
66 mapstruct *m; 64 maptile *m;
67 int mflags; 65 int mflags;
68 66
69 if(op==NULL) { 67 if (op == NULL)
68 {
70 LOG(llevError,"Trying to move NULL.\n"); 69 LOG (llevError, "Trying to move NULL.\n");
71 return 0; 70 return 0;
72 } 71 }
73 72
74 m = op->map; 73 m = op->map;
75 mflags = get_map_flags(m, &m, newx, newy, &newx, &newy); 74 mflags = get_map_flags (m, &m, newx, newy, &newx, &newy);
76 75
77 /* If the space the player is trying to is out of the map, 76 /* If the space the player is trying to is out of the map,
78 * bail now - we know it can't work. 77 * bail now - we know it can't work.
79 */ 78 */
80 if (mflags & P_OUT_OF_MAP) return 0; 79 if (mflags & P_OUT_OF_MAP)
80 return 0;
81 81
82 82
83 /* Is this space blocked? Players with wizpass are immune to 83 /* Is this space blocked? Players with wizpass are immune to
84 * this condition. 84 * this condition.
85 */ 85 */
86 if(blocked_link(op, m, newx, newy) && 86 if (blocked_link (op, m, newx, newy) && !QUERY_FLAG (op, FLAG_WIZPASS))
87 !QUERY_FLAG(op, FLAG_WIZPASS))
88 return 0; 87 return 0;
89 88
90 /* 0.94.2 - we need to set the direction for the new animation code. 89 /* 0.94.2 - we need to set the direction for the new animation code.
91 * it uses it to figure out face to use - I can't see it 90 * it uses it to figure out face to use - I can't see it
92 * breaking anything, but it might. 91 * breaking anything, but it might.
93 */ 92 */
94 if(op->more != NULL && !move_ob(op->more, dir, op->more->head)) 93 if (op->more != NULL && !move_ob (op->more, dir, op->more->head))
95 return 0; 94 return 0;
96 95
97 op->direction = dir; 96 op->direction = dir;
98 97
99 if(op->will_apply&4) 98 if (op->will_apply & 4)
100 check_earthwalls(op,m, newx,newy); 99 check_earthwalls (op, m, newx, newy);
101 if(op->will_apply&8) 100 if (op->will_apply & 8)
102 check_doors(op,m, newx,newy); 101 check_doors (op, m, newx, newy);
103 102
104 /* 0.94.1 - I got a stack trace that showed it crash with remove_ob trying 103 /* 0.94.1 - I got a stack trace that showed it crash with remove_ob trying
105 * to remove a removed object, and this function was the culprit. A possible 104 * to remove a removed object, and this function was the culprit. A possible
106 * guess I have is that check_doors above ran into a trap, killing the 105 * guess I have is that check_doors above ran into a trap, killing the
107 * monster. 106 * monster.
108 * 107 *
109 * Unfortunately, it doesn't appear that the calling functions of move_object 108 * Unfortunately, it doesn't appear that the calling functions of move_object
110 * deal very well with op being killed, so all this might do is just 109 * deal very well with op being killed, so all this might do is just
111 * migrate the problem someplace else. 110 * migrate the problem someplace else.
112 */ 111 */
113 112
114 if (QUERY_FLAG(op, FLAG_REMOVED)) { 113 if (QUERY_FLAG (op, FLAG_REMOVED))
114 {
115 LOG(llevDebug,"move_object: monster has been removed - will not process further\n"); 115 LOG (llevDebug, "move_object: monster has been removed - will not process further\n");
116 /* Was not successful, but don't want to try and move again */ 116 /* Was not successful, but don't want to try and move again */
117 return 1; 117 return 1;
118 } 118 }
119 119
120 /* If this is a tail portion, just want to tell caller that move is 120 /* If this is a tail portion, just want to tell caller that move is
121 * ok - the caller will deal with actual object removal/insertion 121 * ok - the caller will deal with actual object removal/insertion
122 */ 122 */
123 if(op->head) 123 if (op->head)
124 return 1;
125
126 remove_ob(op);
127
128 /* we already have newx, newy, and m, so lets use them.
129 * In addition, this fixes potential crashes, because multipart object was
130 * on edge of map, +=x, +=y doesn't make correct coordinates.
131 */
132 for(tmp = op; tmp != NULL; tmp = tmp->more) {
133 tmp->x += freearr_x[dir];
134 tmp->y += freearr_y[dir];
135 tmp->map = get_map_from_coord(tmp->map, &tmp->x, &tmp->y);
136 }
137
138 /* insert_ob_in_map will deal with any tiling issues */
139 insert_ob_in_map(op, m, originator,0);
140
141 return 1; 124 return 1;
125
126 remove_ob (op);
127
128 /* we already have newx, newy, and m, so lets use them.
129 * In addition, this fixes potential crashes, because multipart object was
130 * on edge of map, +=x, +=y doesn't make correct coordinates.
131 */
132 for (tmp = op; tmp != NULL; tmp = tmp->more)
133 {
134 tmp->x += freearr_x[dir];
135 tmp->y += freearr_y[dir];
136 tmp->map = get_map_from_coord (tmp->map, &tmp->x, &tmp->y);
137 }
138
139 /* insert_ob_in_map will deal with any tiling issues */
140 insert_ob_in_map (op, m, originator, 0);
141
142 return 1;
142} 143}
143 144
144 145
145/* 146/*
146 * transfer_ob(): Move an object (even linked objects) to another spot 147 * transfer_ob(): Move an object (even linked objects) to another spot
152 * use find_first_free_spot(). 153 * use find_first_free_spot().
153 * 154 *
154 * Return value: 1 if object was destroyed, 0 otherwise. 155 * Return value: 1 if object was destroyed, 0 otherwise.
155 */ 156 */
156 157
158int
157int transfer_ob (object *op, int x, int y, int randomly, object *originator) 159transfer_ob (object *op, int x, int y, int randomly, object *originator)
158{ 160{
159 int i; 161 int i;
160 object *tmp; 162 object *tmp;
161 163
162 if (randomly) 164 if (randomly)
163 i = find_free_spot (op,op->map,x,y,0,SIZEOFFREE); 165 i = find_free_spot (op, op->map, x, y, 0, SIZEOFFREE);
164 else 166 else
165 i = find_first_free_spot(op,op->map,x,y); 167 i = find_first_free_spot (op, op->map, x, y);
166 168
167 if (i==-1) 169 if (i == -1)
168 return 0; /* No free spot */ 170 return 0; /* No free spot */
169 171
170 if(op->head!=NULL) 172 if (op->head != NULL)
171 op=op->head; 173 op = op->head;
172 remove_ob(op); 174 remove_ob (op);
173 for(tmp=op;tmp!=NULL;tmp=tmp->more) 175 for (tmp = op; tmp != NULL; tmp = tmp->more)
174 tmp->x=x+freearr_x[i]+(tmp->arch==NULL?0:tmp->arch->clone.x), 176 tmp->x = x + freearr_x[i] + (tmp->arch == NULL ? 0 : tmp->arch->clone.x),
175 tmp->y=y+freearr_y[i]+(tmp->arch==NULL?0:tmp->arch->clone.y); 177 tmp->y = y + freearr_y[i] + (tmp->arch == NULL ? 0 : tmp->arch->clone.y);
176 178
177 tmp = insert_ob_in_map(op,op->map,originator,0); 179 tmp = insert_ob_in_map (op, op->map, originator, 0);
178 if (tmp) return 0; 180 if (tmp)
181 return 0;
182 else
179 else return 1; 183 return 1;
180} 184}
181 185
182/* 186/*
183 * Return value: 1 if object was destroyed, 0 otherwise. 187 * Return value: 1 if object was destroyed, 0 otherwise.
184 * Modified so that instead of passing the 'originator' that had no 188 * Modified so that instead of passing the 'originator' that had no
189 * currently, this is either set to SHOP_MAT or TELEPORTER. 193 * currently, this is either set to SHOP_MAT or TELEPORTER.
190 * It is basically used so that shop_mats and normal teleporters can 194 * It is basically used so that shop_mats and normal teleporters can
191 * be used close to each other and not have the player put to the 195 * be used close to each other and not have the player put to the
192 * one of another type. 196 * one of another type.
193 */ 197 */
198int
194int teleport (object *teleporter, uint8 tele_type, object *user) 199teleport (object *teleporter, uint8 tele_type, object *user)
195{ 200{
196 object *altern; 201 object *altern;
197 int i,j,k,nrofalt=0; 202 int i, j, k, nrofalt = 0;
198 object *other_teleporter, *tmp; 203 object *other_teleporter, *tmp;
199 mapstruct *m; 204 maptile *m;
200 sint16 sx, sy; 205 sint16 sx, sy;
201 206
202 if(user==NULL) return 0; 207 if (user == NULL)
208 return 0;
203 if(user->head!=NULL) 209 if (user->head != NULL)
204 user=user->head; 210 user = user->head;
205 211
206 /* Find all other teleporters within range. This range 212 /* Find all other teleporters within range. This range
207 * should really be setable by some object attribute instead of 213 * should really be setable by some object attribute instead of
208 * using hard coded values. 214 * using hard coded values.
209 */ 215 */
210 for(i= -5;i<6;i++) 216 for (i = -5; i < 6; i++)
211 for(j= -5;j<6;j++) { 217 for (j = -5; j < 6; j++)
218 {
212 if(i==0&&j==0) 219 if (i == 0 && j == 0)
220 continue;
221 /* Perhaps this should be extended to support tiled maps */
222 if (OUT_OF_REAL_MAP (teleporter->map, teleporter->x + i, teleporter->y + j))
223 continue;
224 other_teleporter = get_map_ob (teleporter->map, teleporter->x + i, teleporter->y + j);
225
226 while (other_teleporter)
227 {
228 if (other_teleporter->type == tele_type)
229 break;
230 other_teleporter = other_teleporter->above;
231 }
232 if (other_teleporter && !(RANDOM () % ++nrofalt))
233 altern = other_teleporter;
234 }
235
236 if (!nrofalt)
237 {
238 LOG (llevError, "No alternative teleporters around!\n");
239 return 0;
240 }
241
242 other_teleporter = altern;
243 k = find_free_spot (user, other_teleporter->map, other_teleporter->x, other_teleporter->y, 1, 9);
244
245 /* if k==-1, unable to find a free spot. If this is shop
246 * mat that the player is using, find someplace to move
247 * the player - otherwise, player can get trapped in the shops
248 * that appear in random dungeons. We basically just make
249 * sure the space isn't no pass (eg wall), and don't care
250 * about is alive.
251 */
252 if (k == -1)
253 {
254 if (tele_type == SHOP_MAT && user->type == PLAYER)
255 {
256 for (k = 1; k < 9; k++)
257 {
258 if (get_map_flags (other_teleporter->map, &m,
259 other_teleporter->x + freearr_x[k], other_teleporter->y + freearr_y[k], &sx, &sy) & P_OUT_OF_MAP)
213 continue; 260 continue;
214 /* Perhaps this should be extended to support tiled maps */ 261
215 if(OUT_OF_REAL_MAP(teleporter->map,teleporter->x+i,teleporter->y+j)) 262 if (!OB_TYPE_MOVE_BLOCK (user, GET_MAP_MOVE_BLOCK (m, sx, sy)))
216 continue; 263 break;
217 other_teleporter=get_map_ob(teleporter->map,
218 teleporter->x+i,teleporter->y+j);
219 264
220 while (other_teleporter) {
221 if (other_teleporter->type == tele_type) break;
222 other_teleporter = other_teleporter->above;
223 } 265 }
224 if (other_teleporter && !(RANDOM() % ++nrofalt)) 266 if (k == 9)
225 altern = other_teleporter;
226 }
227
228 if(!nrofalt) {
229 LOG(llevError,"No alternative teleporters around!\n");
230 return 0;
231 }
232
233 other_teleporter=altern;
234 k=find_free_spot(user,other_teleporter->map,
235 other_teleporter->x,other_teleporter->y,1,9);
236
237 /* if k==-1, unable to find a free spot. If this is shop
238 * mat that the player is using, find someplace to move
239 * the player - otherwise, player can get trapped in the shops
240 * that appear in random dungeons. We basically just make
241 * sure the space isn't no pass (eg wall), and don't care
242 * about is alive.
243 */
244 if (k==-1) {
245 if (tele_type == SHOP_MAT && user->type == PLAYER) {
246 for (k=1; k<9; k++) {
247 if (get_map_flags(other_teleporter->map, &m,
248 other_teleporter->x + freearr_x[k],
249 other_teleporter->y + freearr_y[k], &sx,&sy) &
250 P_OUT_OF_MAP) continue;
251
252 if (!OB_TYPE_MOVE_BLOCK(user, GET_MAP_MOVE_BLOCK(m, sx, sy))) break;
253
254 } 267 {
255 if (k==9) {
256 LOG(llevError,"Shop mat %s (%d, %d) is in solid rock?\n", 268 LOG (llevError, "Shop mat %s (%d, %d) is in solid rock?\n",
257 &other_teleporter->name, other_teleporter->x, other_teleporter->y); 269 &other_teleporter->name, other_teleporter->x, other_teleporter->y);
258 return 0; 270 return 0;
259 } 271 }
260 } 272 }
273 else
261 else return 0; 274 return 0;
262 } 275 }
263 276
264 remove_ob(user); 277 remove_ob (user);
265 278
266 /* Update location for the object */ 279 /* Update location for the object */
267 for(tmp=user;tmp!=NULL;tmp=tmp->more) { 280 for (tmp = user; tmp != NULL; tmp = tmp->more)
268 tmp->x=other_teleporter->x+freearr_x[k]+
269 (tmp->arch==NULL?0:tmp->arch->clone.x);
270 tmp->y=other_teleporter->y+freearr_y[k]+
271 (tmp->arch==NULL?0:tmp->arch->clone.y);
272 } 281 {
282 tmp->x = other_teleporter->x + freearr_x[k] + (tmp->arch == NULL ? 0 : tmp->arch->clone.x);
283 tmp->y = other_teleporter->y + freearr_y[k] + (tmp->arch == NULL ? 0 : tmp->arch->clone.y);
284 }
273 tmp = insert_ob_in_map(user,other_teleporter->map,NULL,0); 285 tmp = insert_ob_in_map (user, other_teleporter->map, NULL, 0);
274 return (tmp == NULL); 286 return (tmp == NULL);
275} 287}
276 288
289void
277void recursive_roll(object *op,int dir,object *pusher) { 290recursive_roll (object *op, int dir, object *pusher)
291{
278 if(!roll_ob(op,dir,pusher)) { 292 if (!roll_ob (op, dir, pusher))
279 new_draw_info_format(NDI_UNIQUE, 0, pusher, 293 {
280 "You fail to push the %s.",query_name(op)); 294 new_draw_info_format (NDI_UNIQUE, 0, pusher, "You fail to push the %s.", query_name (op));
281 return; 295 return;
282 } 296 }
283 (void) move_ob(pusher,dir,pusher); 297 (void) move_ob (pusher, dir, pusher);
284 new_draw_info_format(NDI_BLACK, 0, pusher, 298 new_draw_info_format (NDI_BLACK, 0, pusher, "You move the %s.", query_name (op));
285 "You move the %s.",query_name(op));
286 return; 299 return;
287} 300}
288 301
289/* 302/*
290 * This is a new version of blocked, this one handles objects 303 * This is a new version of blocked, this one handles objects
293 * very new version handles also multipart objects 306 * very new version handles also multipart objects
294 * This is currently only used for the boulder roll code. 307 * This is currently only used for the boulder roll code.
295 * Returns 1 if object does not fit, 0 if it does. 308 * Returns 1 if object does not fit, 0 if it does.
296 */ 309 */
297 310
311int
298int try_fit (object *op, mapstruct *m, int x, int y) 312try_fit (object *op, maptile *m, int x, int y)
299{ 313{
300 object *tmp, *more; 314 object *tmp, *more;
301 sint16 tx, ty; 315 sint16 tx, ty;
302 int mflags; 316 int mflags;
303 mapstruct *m2; 317 maptile *m2;
304 318
305 if (op->head) 319 if (op->head)
306 op = op->head; 320 op = op->head;
307 321
308 for (more = op; more ; more = more->more) { 322 for (more = op; more; more = more->more)
323 {
309 tx = x + more->x - op->x; 324 tx = x + more->x - op->x;
310 ty = y + more->y - op->y; 325 ty = y + more->y - op->y;
311 326
312 mflags = get_map_flags(m, &m2, tx, ty, &tx, &ty); 327 mflags = get_map_flags (m, &m2, tx, ty, &tx, &ty);
313 328
314 if (mflags & P_OUT_OF_MAP) 329 if (mflags & P_OUT_OF_MAP)
330 return 1;
331
332 for (tmp = get_map_ob (m2, tx, ty); tmp; tmp = tmp->above)
333 {
334 if (tmp->head == op || tmp == op)
335 continue;
336
337 if ((QUERY_FLAG (tmp, FLAG_ALIVE) && tmp->type != DOOR))
315 return 1; 338 return 1;
316 339
317 for (tmp = get_map_ob (m2, tx, ty); tmp; tmp=tmp->above) { 340 if (OB_MOVE_BLOCK (op, tmp))
318 if (tmp->head == op || tmp == op)
319 continue;
320
321 if ((QUERY_FLAG(tmp,FLAG_ALIVE) && tmp->type!=DOOR))
322 return 1; 341 return 1;
323
324 if (OB_MOVE_BLOCK(op, tmp)) return 1;
325 342
326 } 343 }
327 } 344 }
328 return 0; 345 return 0;
329} 346}
330 347
331/* 348/*
332 * this is not perfect yet. 349 * this is not perfect yet.
333 * it does not roll objects behind multipart objects properly. 350 * it does not roll objects behind multipart objects properly.
334 * Support for rolling multipart objects is questionable. 351 * Support for rolling multipart objects is questionable.
335 */ 352 */
336 353
354int
337int roll_ob(object *op,int dir, object *pusher) { 355roll_ob (object *op, int dir, object *pusher)
356{
338 object *tmp; 357 object *tmp;
339 sint16 x, y; 358 sint16 x, y;
340 int flags; 359 int flags;
341 mapstruct *m; 360 maptile *m;
342 MoveType move_block; 361 MoveType move_block;
343 362
344 if (op->head) 363 if (op->head)
345 op = op->head; 364 op = op->head;
346 365
347 x=op->x+freearr_x[dir]; 366 x = op->x + freearr_x[dir];
348 y=op->y+freearr_y[dir]; 367 y = op->y + freearr_y[dir];
349 368
350 if(!QUERY_FLAG(op,FLAG_CAN_ROLL) || 369 if (!QUERY_FLAG (op, FLAG_CAN_ROLL) || (op->weight && random_roll (0, op->weight / 50000 - 1, pusher, PREFER_LOW) > pusher->stats.Str))
351 (op->weight &&
352 random_roll(0, op->weight/50000-1, pusher, PREFER_LOW) > pusher->stats.Str))
353 return 0; 370 return 0;
354 371
355 m = op->map; 372 m = op->map;
356 flags = get_map_flags(m, &m, x, y, &x, &y); 373 flags = get_map_flags (m, &m, x, y, &x, &y);
357 374
358 if (flags & (P_OUT_OF_MAP | P_IS_ALIVE)) 375 if (flags & (P_OUT_OF_MAP | P_IS_ALIVE))
359 return 0; 376 return 0;
360 377
361 move_block = GET_MAP_MOVE_BLOCK(m, x, y); 378 move_block = GET_MAP_MOVE_BLOCK (m, x, y);
362 379
363 /* If the target space is not blocked, no need to look at the objects on it */ 380 /* If the target space is not blocked, no need to look at the objects on it */
364 if ((op->move_type & move_block) == op->move_type) { 381 if ((op->move_type & move_block) == op->move_type)
382 {
365 for (tmp=get_map_ob(m, x, y); tmp!=NULL; tmp=tmp->above) { 383 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = tmp->above)
384 {
366 if (tmp->head == op) 385 if (tmp->head == op)
367 continue; 386 continue;
368 if (OB_MOVE_BLOCK(op, tmp) && !roll_ob(tmp,dir,pusher)) 387 if (OB_MOVE_BLOCK (op, tmp) && !roll_ob (tmp, dir, pusher))
369 return 0; 388 return 0;
370 } 389 }
371 } 390 }
372 if (try_fit (op, m, x, y)) 391 if (try_fit (op, m, x, y))
373 return 0; 392 return 0;
374 393
375 remove_ob(op); 394 remove_ob (op);
376 for(tmp=op; tmp!=NULL; tmp=tmp->more) 395 for (tmp = op; tmp != NULL; tmp = tmp->more)
377 tmp->x+=freearr_x[dir],tmp->y+=freearr_y[dir]; 396 tmp->x += freearr_x[dir], tmp->y += freearr_y[dir];
378 insert_ob_in_map(op,op->map,pusher,0); 397 insert_ob_in_map (op, op->map, pusher, 0);
379 return 1; 398 return 1;
380} 399}
381 400
382/* returns 1 if pushing invokes a attack, 0 when not */ 401/* returns 1 if pushing invokes a attack, 0 when not */
402int
383int push_ob(object *who, int dir, object *pusher) { 403push_ob (object *who, int dir, object *pusher)
404{
384 int str1, str2; 405 int str1, str2;
385 object *owner; 406 object *owner;
386 407
387 if (who->head != NULL) 408 if (who->head != NULL)
388 who = who->head; 409 who = who->head;
389 owner = get_owner(who); 410 owner = get_owner (who);
390 411
391 /* Wake up sleeping monsters that may be pushed */ 412 /* Wake up sleeping monsters that may be pushed */
392 CLEAR_FLAG(who,FLAG_SLEEP); 413 CLEAR_FLAG (who, FLAG_SLEEP);
393 414
394 /* player change place with his pets or summoned creature */ 415 /* player change place with his pets or summoned creature */
395 /* TODO: allow multi arch pushing. Can't be very difficult */ 416 /* TODO: allow multi arch pushing. Can't be very difficult */
396 if (who->more == NULL 417 if (who->more == NULL
397#ifdef COZY_SERVER 418#ifdef COZY_SERVER
398 && 419 && ((owner && owner->contr && pusher->contr && same_party (owner->contr->party, pusher->contr->party)) || owner == pusher)
399 (
400 (owner && owner->contr && pusher->contr
401 && same_party (owner->contr->party, pusher->contr->party))
402 || owner == pusher
403 )
404#else 420#else
405 && owner == pusher 421 && owner == pusher
406#endif 422#endif
407 ) { 423 )
424 {
408 int temp; 425 int temp;
409 mapstruct *m; 426 maptile *m;
410 427
411 remove_ob(who); 428 remove_ob (who);
412 remove_ob(pusher); 429 remove_ob (pusher);
413 temp = pusher->x; 430 temp = pusher->x;
414 pusher->x = who->x; 431 pusher->x = who->x;
415 who->x = temp; 432 who->x = temp;
416 433
417 temp = pusher->y; 434 temp = pusher->y;
418 pusher->y = who->y; 435 pusher->y = who->y;
419 who->y = temp; 436 who->y = temp;
420 437
421 m = pusher->map; 438 m = pusher->map;
422 pusher->map = who->map; 439 pusher->map = who->map;
423 who->map = m; 440 who->map = m;
424 441
425 insert_ob_in_map (who,who->map,pusher,0); 442 insert_ob_in_map (who, who->map, pusher, 0);
426 insert_ob_in_map (pusher,pusher->map,pusher,0); 443 insert_ob_in_map (pusher, pusher->map, pusher, 0);
427 return 0; 444 return 0;
428 } 445 }
429 446
430 447
431 /* We want ONLY become enemy of evil, unaggressive monster. We must RUN in them */ 448 /* We want ONLY become enemy of evil, unaggressive monster. We must RUN in them */
432 /* In original we have here a unaggressive check only - that was the reason why */ 449 /* In original we have here a unaggressive check only - that was the reason why */
433 /* we so often become an enemy of friendly monsters... */ 450 /* we so often become an enemy of friendly monsters... */
434 /* funny: was they set to unaggressive 0 (= not so nice) they don't attack */ 451 /* funny: was they set to unaggressive 0 (= not so nice) they don't attack */
435 452
436 if(owner != pusher && pusher->type == PLAYER && who->type != PLAYER && 453 if (owner != pusher && pusher->type == PLAYER && who->type != PLAYER &&
437 !QUERY_FLAG(who,FLAG_FRIENDLY)&& !QUERY_FLAG(who,FLAG_NEUTRAL)) { 454 !QUERY_FLAG (who, FLAG_FRIENDLY) && !QUERY_FLAG (who, FLAG_NEUTRAL))
455 {
438 if(pusher->contr->run_on) /* only when we run */ { 456 if (pusher->contr->run_on) /* only when we run */
439 new_draw_info_format(NDI_UNIQUE, 0, pusher, 457 {
440 "You start to attack %s !!", &who->name); 458 new_draw_info_format (NDI_UNIQUE, 0, pusher, "You start to attack %s !!", &who->name);
441 CLEAR_FLAG(who,FLAG_UNAGGRESSIVE); /* the sucker don't like you anymore */ 459 CLEAR_FLAG (who, FLAG_UNAGGRESSIVE); /* the sucker don't like you anymore */
442 who->enemy = pusher; 460 who->enemy = pusher;
443 return 1; 461 return 1;
444 } 462 }
445 else 463 else
446 { 464 {
447 new_draw_info_format(NDI_UNIQUE, 0, pusher, 465 new_draw_info_format (NDI_UNIQUE, 0, pusher, "You avoid attacking %s.", &who->name);
448 "You avoid attacking %s.", &who->name);
449 } 466 }
450 } 467 }
451 468
452 /* now, lets test stand still. we NEVER can push stand_still monsters. */ 469 /* now, lets test stand still. we NEVER can push stand_still monsters. */
453 if(QUERY_FLAG(who,FLAG_STAND_STILL)) 470 if (QUERY_FLAG (who, FLAG_STAND_STILL))
454 { 471 {
455 new_draw_info_format(NDI_UNIQUE, 0, pusher, 472 new_draw_info_format (NDI_UNIQUE, 0, pusher, "You can't push %s.", &who->name);
456 "You can't push %s.", &who->name);
457 return 0; 473 return 0;
458 } 474 }
459 475
460 /* This block is basically if you are pushing friendly but 476 /* This block is basically if you are pushing friendly but
461 * non pet creaturs. 477 * non pet creaturs.
462 * It basically does a random strength comparision to 478 * It basically does a random strength comparision to
463 * determine if you can push someone around. Note that 479 * determine if you can push someone around. Note that
464 * this pushes the other person away - its not a swap. 480 * this pushes the other person away - its not a swap.
465 */ 481 */
466 482
467 str1 = (who->stats.Str>0?who->stats.Str:who->level); 483 str1 = (who->stats.Str > 0 ? who->stats.Str : who->level);
468 str2 = (pusher->stats.Str>0?pusher->stats.Str:pusher->level); 484 str2 = (pusher->stats.Str > 0 ? pusher->stats.Str : pusher->level);
469 if(QUERY_FLAG(who,FLAG_WIZ) || 485 if (QUERY_FLAG (who, FLAG_WIZ) ||
470 random_roll(str1, str1/2+str1*2, who, PREFER_HIGH) >= 486 random_roll (str1, str1 / 2 + str1 * 2, who, PREFER_HIGH) >=
471 random_roll(str2, str2/2+str2*2, pusher, PREFER_HIGH) || 487 random_roll (str2, str2 / 2 + str2 * 2, pusher, PREFER_HIGH) || !move_object (who, dir))
472 !move_object(who,dir))
473 { 488 {
474 if (who ->type == PLAYER) { 489 if (who->type == PLAYER)
475 new_draw_info_format(NDI_UNIQUE, 0, who, 490 {
476 "%s tried to push you.", &pusher->name); 491 new_draw_info_format (NDI_UNIQUE, 0, who, "%s tried to push you.", &pusher->name);
477 } 492 }
478 return 0; 493 return 0;
479 } 494 }
480 495
481 /* If we get here, the push succeeded. 496 /* If we get here, the push succeeded.
482 * Let everyone know the status. 497 * Let everyone know the status.
483 */ 498 */
484 if (who->type == PLAYER) { 499 if (who->type == PLAYER)
485 new_draw_info_format(NDI_UNIQUE, 0, who,
486 "%s pushed you.", &pusher->name);
487 } 500 {
501 new_draw_info_format (NDI_UNIQUE, 0, who, "%s pushed you.", &pusher->name);
502 }
488 if (pusher->type == PLAYER) { 503 if (pusher->type == PLAYER)
489 new_draw_info_format(NDI_UNIQUE, 0, pusher,
490 "You pushed %s back.", &who->name);
491 } 504 {
492 505 new_draw_info_format (NDI_UNIQUE, 0, pusher, "You pushed %s back.", &who->name);
506 }
507
493 return 1; 508 return 1;
494} 509}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines