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.4 by root, Tue Aug 29 08:01:37 2006 UTC vs.
Revision 1.14 by pippijn, Sat Jan 6 14:42:31 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines