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.2 by root, Thu Aug 17 20:23:31 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.2 2006/08/17 20:23:31 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; 71 return 0;
72 } 72 }
73 73
74 m = op->map; 74 m = op->map;
75 mflags = get_map_flags(m, &m, newx, newy, &newx, &newy); 75 mflags = get_map_flags (m, &m, newx, newy, &newx, &newy);
76 76
77 /* If the space the player is trying to is out of the map, 77 /* If the space the player is trying to is out of the map,
78 * bail now - we know it can't work. 78 * bail now - we know it can't work.
79 */ 79 */
80 if (mflags & P_OUT_OF_MAP) return 0; 80 if (mflags & P_OUT_OF_MAP)
81 return 0;
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 && !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);
100
101 if(op->will_apply&8) 101 if (op->will_apply & 8)
102 check_doors(op,m, newx,newy); 102 check_doors (op, m, newx, newy);
103 103
104 /* 0.94.1 - I got a stack trace that showed it crash with remove_ob trying 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 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 106 * guess I have is that check_doors above ran into a trap, killing the
107 * monster. 107 * monster.
108 * 108 *
109 * Unfortunately, it doesn't appear that the calling functions of move_object 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 110 * deal very well with op being killed, so all this might do is just
111 * migrate the problem someplace else. 111 * migrate the problem someplace else.
112 */ 112 */
113 113
114 if (QUERY_FLAG(op, FLAG_REMOVED)) { 114 if (QUERY_FLAG (op, FLAG_REMOVED))
115 {
115 LOG(llevDebug,"move_object: monster has been removed - will not process further\n"); 116 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 /* Was not successful, but don't want to try and move again */
117 return 1; 118 return 1;
118 } 119 }
119 120
120 /* If this is a tail portion, just want to tell caller that move is 121 /* 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 * ok - the caller will deal with actual object removal/insertion
122 */ 123 */
123 if(op->head) 124 if (op->head)
124 return 1; 125 return 1;
125 126
126 remove_ob(op); 127 if (m != op->map && op->contr)
128 {
129 if (INVOKE_MAP (LEAVE, op->map, ARG_PLAYER (op->contr)))
130 return 0;
127 131
132 op->remove ();
133
134 if (INVOKE_PLAYER (MAP_CHANGE, op->contr, ARG_MAP (m), ARG_INT (newx), ARG_INT (newy)))
135 return 0;
136
137 if (INVOKE_MAP (ENTER, m, ARG_PLAYER (op->contr), ARG_INT (newx), ARG_INT (newy)))
138 return 0;
139 }
140 else
141 op->remove ();
142
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 /* Hmmm. Should be possible for multispace players now */ 157 return 1;
142 if (op->type == TRANSPORT) {
143 object *pl;
144
145 for (pl=op->inv; pl; pl=pl->below) {
146 if (pl->type == PLAYER) {
147 pl->contr->do_los=1;
148 pl->map = op->map;
149 pl->x = op->x;
150 pl->y = op->y;
151 }
152 }
153 }
154
155 return 1; /* this shouldn't be reached */
156} 158}
157 159
158 160
159/* 161/*
160 * transfer_ob(): Move an object (even linked objects) to another spot 162 * transfer_ob(): Move an object (even linked objects) to another spot
166 * use find_first_free_spot(). 168 * use find_first_free_spot().
167 * 169 *
168 * Return value: 1 if object was destroyed, 0 otherwise. 170 * Return value: 1 if object was destroyed, 0 otherwise.
169 */ 171 */
170 172
173int
171int transfer_ob (object *op, int x, int y, int randomly, object *originator) 174transfer_ob (object *op, int x, int y, int randomly, object *originator)
172{ 175{
173 int i; 176 int i;
174 object *tmp; 177 object *tmp;
175 178
176 if (randomly) 179 if (randomly)
177 i = find_free_spot (op,op->map,x,y,0,SIZEOFFREE); 180 i = find_free_spot (op, op->map, x, y, 0, SIZEOFFREE);
178 else 181 else
179 i = find_first_free_spot(op,op->map,x,y); 182 i = find_first_free_spot (op, op->map, x, y);
180 183
181 if (i==-1) 184 if (i == -1)
182 return 0; /* No free spot */ 185 return 0; /* No free spot */
183 186
184 if(op->head!=NULL) 187 if (op->head != NULL)
185 op=op->head; 188 op = op->head;
186 remove_ob(op); 189 op->remove ();
187 for(tmp=op;tmp!=NULL;tmp=tmp->more) 190 for (tmp = op; tmp != NULL; tmp = tmp->more)
188 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),
189 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);
190 193
191 tmp = insert_ob_in_map(op,op->map,originator,0); 194 tmp = insert_ob_in_map (op, op->map, originator, 0);
192 if (tmp) return 0; 195 if (tmp)
196 return 0;
197 else
193 else return 1; 198 return 1;
194} 199}
195 200
196/* 201/*
197 * Return value: 1 if object was destroyed, 0 otherwise. 202 * Return value: 1 if object was destroyed, 0 otherwise.
198 * Modified so that instead of passing the 'originator' that had no 203 * Modified so that instead of passing the 'originator' that had no
203 * currently, this is either set to SHOP_MAT or TELEPORTER. 208 * currently, this is either set to SHOP_MAT or TELEPORTER.
204 * 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
205 * 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
206 * one of another type. 211 * one of another type.
207 */ 212 */
213int
208int teleport (object *teleporter, uint8 tele_type, object *user) 214teleport (object *teleporter, uint8 tele_type, object *user)
209{ 215{
210 object *altern; 216 object *altern;
211 int i,j,k,nrofalt=0; 217 int i, j, k, nrofalt = 0;
212 object *other_teleporter, *tmp; 218 object *other_teleporter, *tmp;
213 mapstruct *m; 219 maptile *m;
214 sint16 sx, sy; 220 sint16 sx, sy;
215 221
216 if(user==NULL) return 0; 222 if (user == NULL)
223 return 0;
217 if(user->head!=NULL) 224 if (user->head != NULL)
218 user=user->head; 225 user = user->head;
219 226
220 /* Find all other teleporters within range. This range 227 /* Find all other teleporters within range. This range
221 * should really be setable by some object attribute instead of 228 * should really be setable by some object attribute instead of
222 * using hard coded values. 229 * using hard coded values.
223 */ 230 */
224 for(i= -5;i<6;i++) 231 for (i = -5; i < 6; i++)
225 for(j= -5;j<6;j++) { 232 for (j = -5; j < 6; j++)
233 {
226 if(i==0&&j==0) 234 if (i == 0 && j == 0)
227 continue; 235 continue;
228 /* Perhaps this should be extended to support tiled maps */ 236 /* Perhaps this should be extended to support tiled maps */
229 if(OUT_OF_REAL_MAP(teleporter->map,teleporter->x+i,teleporter->y+j)) 237 if (OUT_OF_REAL_MAP (teleporter->map, teleporter->x + i, teleporter->y + j))
230 continue; 238 continue;
231 other_teleporter=get_map_ob(teleporter->map, 239 other_teleporter = GET_MAP_OB (teleporter->map, teleporter->x + i, teleporter->y + j);
232 teleporter->x+i,teleporter->y+j);
233 240
234 while (other_teleporter) { 241 while (other_teleporter)
242 {
235 if (other_teleporter->type == tele_type) break; 243 if (other_teleporter->type == tele_type)
244 break;
236 other_teleporter = other_teleporter->above; 245 other_teleporter = other_teleporter->above;
237 } 246 }
238 if (other_teleporter && !(RANDOM() % ++nrofalt)) 247 if (other_teleporter && !(RANDOM () % ++nrofalt))
239 altern = other_teleporter; 248 altern = other_teleporter;
240 } 249 }
241 250
242 if(!nrofalt) { 251 if (!nrofalt)
252 {
243 LOG(llevError,"No alternative teleporters around!\n"); 253 LOG (llevError, "No alternative teleporters around!\n");
244 return 0; 254 return 0;
245 } 255 }
246 256
247 other_teleporter=altern; 257 other_teleporter = altern;
248 k=find_free_spot(user,other_teleporter->map, 258 k = find_free_spot (user, other_teleporter->map, other_teleporter->x, other_teleporter->y, 1, 9);
249 other_teleporter->x,other_teleporter->y,1,9);
250 259
251 /* if k==-1, unable to find a free spot. If this is shop 260 /* if k==-1, unable to find a free spot. If this is shop
252 * mat that the player is using, find someplace to move 261 * mat that the player is using, find someplace to move
253 * the player - otherwise, player can get trapped in the shops 262 * the player - otherwise, player can get trapped in the shops
254 * that appear in random dungeons. We basically just make 263 * that appear in random dungeons. We basically just make
255 * sure the space isn't no pass (eg wall), and don't care 264 * sure the space isn't no pass (eg wall), and don't care
256 * about is alive. 265 * about is alive.
257 */ 266 */
258 if (k==-1) { 267 if (k == -1)
268 {
259 if (tele_type == SHOP_MAT && user->type == PLAYER) { 269 if (tele_type == SHOP_MAT && user->type == PLAYER)
270 {
260 for (k=1; k<9; k++) { 271 for (k = 1; k < 9; k++)
272 {
261 if (get_map_flags(other_teleporter->map, &m, 273 if (get_map_flags (other_teleporter->map, &m,
262 other_teleporter->x + freearr_x[k], 274 other_teleporter->x + freearr_x[k], other_teleporter->y + freearr_y[k], &sx, &sy) & P_OUT_OF_MAP)
263 other_teleporter->y + freearr_y[k], &sx,&sy) & 275 continue;
264 P_OUT_OF_MAP) continue;
265 276
266 if (!OB_TYPE_MOVE_BLOCK(user, GET_MAP_MOVE_BLOCK(m, sx, sy))) break; 277 if (!OB_TYPE_MOVE_BLOCK (user, GET_MAP_MOVE_BLOCK (m, sx, sy)))
278 break;
267 279
280 }
281 if (k == 9)
282 {
283 LOG (llevError, "Shop mat %s (%d, %d) is in solid rock?\n",
284 &other_teleporter->name, other_teleporter->x, other_teleporter->y);
285 return 0;
286 }
287 }
288 else
289 return 0;
268 } 290 }
269 if (k==9) {
270 LOG(llevError,"Shop mat %s (%d, %d) is in solid rock?\n",
271 other_teleporter->name, other_teleporter->x, other_teleporter->y);
272 return 0;
273 }
274 }
275 else return 0;
276 }
277 291
278 remove_ob(user); 292 user->remove ();
279 293
280 /* Update location for the object */ 294 /* Update location for the object */
281 for(tmp=user;tmp!=NULL;tmp=tmp->more) { 295 for (tmp = user; tmp != NULL; tmp = tmp->more)
282 tmp->x=other_teleporter->x+freearr_x[k]+
283 (tmp->arch==NULL?0:tmp->arch->clone.x);
284 tmp->y=other_teleporter->y+freearr_y[k]+
285 (tmp->arch==NULL?0:tmp->arch->clone.y);
286 } 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 }
287 tmp = insert_ob_in_map(user,other_teleporter->map,NULL,0); 300 tmp = insert_ob_in_map (user, other_teleporter->map, NULL, 0);
288 return (tmp == NULL); 301 return (tmp == NULL);
289} 302}
290 303
304void
291void recursive_roll(object *op,int dir,object *pusher) { 305recursive_roll (object *op, int dir, object *pusher)
306{
292 if(!roll_ob(op,dir,pusher)) { 307 if (!roll_ob (op, dir, pusher))
293 new_draw_info_format(NDI_UNIQUE, 0, pusher, 308 {
294 "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));
295 return; 310 return;
296 } 311 }
297 (void) move_ob(pusher,dir,pusher); 312 (void) move_ob (pusher, dir, pusher);
298 new_draw_info_format(NDI_BLACK, 0, pusher, 313 new_draw_info_format (NDI_BLACK, 0, pusher, "You move the %s.", query_name (op));
299 "You move the %s.",query_name(op));
300 return; 314 return;
301} 315}
302 316
303/* 317/*
304 * This is a new version of blocked, this one handles objects 318 * This is a new version of blocked, this one handles objects
307 * very new version handles also multipart objects 321 * very new version handles also multipart objects
308 * This is currently only used for the boulder roll code. 322 * This is currently only used for the boulder roll code.
309 * Returns 1 if object does not fit, 0 if it does. 323 * Returns 1 if object does not fit, 0 if it does.
310 */ 324 */
311 325
326int
312int try_fit (object *op, mapstruct *m, int x, int y) 327try_fit (object *op, maptile *m, int x, int y)
313{ 328{
314 object *tmp, *more; 329 object *tmp, *more;
315 sint16 tx, ty; 330 sint16 tx, ty;
316 int mflags; 331 int mflags;
317 mapstruct *m2; 332 maptile *m2;
318 333
319 if (op->head) 334 if (op->head)
320 op = op->head; 335 op = op->head;
321 336
322 for (more = op; more ; more = more->more) { 337 for (more = op; more; more = more->more)
338 {
323 tx = x + more->x - op->x; 339 tx = x + more->x - op->x;
324 ty = y + more->y - op->y; 340 ty = y + more->y - op->y;
325 341
326 mflags = get_map_flags(m, &m2, tx, ty, &tx, &ty); 342 mflags = get_map_flags (m, &m2, tx, ty, &tx, &ty);
327 343
328 if (mflags & P_OUT_OF_MAP) 344 if (mflags & P_OUT_OF_MAP)
329 return 1; 345 return 1;
330 346
331 for (tmp = get_map_ob (m2, tx, ty); tmp; tmp=tmp->above) { 347 for (tmp = GET_MAP_OB (m2, tx, ty); tmp; tmp = tmp->above)
348 {
332 if (tmp->head == op || tmp == op) 349 if (tmp->head == op || tmp == op)
333 continue; 350 continue;
334 351
335 if ((QUERY_FLAG(tmp,FLAG_ALIVE) && tmp->type!=DOOR)) 352 if ((QUERY_FLAG (tmp, FLAG_ALIVE) && tmp->type != DOOR))
336 return 1; 353 return 1;
337 354
338 if (OB_MOVE_BLOCK(op, tmp)) return 1; 355 if (OB_MOVE_BLOCK (op, tmp))
356 return 1;
339 357
340 } 358 }
341 } 359 }
342 return 0; 360 return 0;
343} 361}
344 362
345/* 363/*
346 * this is not perfect yet. 364 * this is not perfect yet.
347 * it does not roll objects behind multipart objects properly. 365 * it does not roll objects behind multipart objects properly.
348 * Support for rolling multipart objects is questionable. 366 * Support for rolling multipart objects is questionable.
349 */ 367 */
350 368
369int
351int roll_ob(object *op,int dir, object *pusher) { 370roll_ob (object *op, int dir, object *pusher)
371{
352 object *tmp; 372 object *tmp;
353 sint16 x, y; 373 sint16 x, y;
354 int flags; 374 int flags;
355 mapstruct *m; 375 maptile *m;
356 MoveType move_block; 376 MoveType move_block;
357 377
358 if (op->head) 378 if (op->head)
359 op = op->head; 379 op = op->head;
360 380
361 x=op->x+freearr_x[dir]; 381 x = op->x + freearr_x[dir];
362 y=op->y+freearr_y[dir]; 382 y = op->y + freearr_y[dir];
363 383
364 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))
365 (op->weight &&
366 random_roll(0, op->weight/50000-1, pusher, PREFER_LOW) > pusher->stats.Str))
367 return 0; 385 return 0;
368 386
369 m = op->map; 387 m = op->map;
370 flags = get_map_flags(m, &m, x, y, &x, &y); 388 flags = get_map_flags (m, &m, x, y, &x, &y);
371 389
372 if (flags & (P_OUT_OF_MAP | P_IS_ALIVE)) 390 if (flags & (P_OUT_OF_MAP | P_IS_ALIVE))
373 return 0; 391 return 0;
374 392
375 move_block = GET_MAP_MOVE_BLOCK(m, x, y); 393 move_block = GET_MAP_MOVE_BLOCK (m, x, y);
376 394
377 /* 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 */
378 if ((op->move_type & move_block) == op->move_type) { 396 if ((op->move_type & move_block) == op->move_type)
397 {
379 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 {
380 if (tmp->head == op) 400 if (tmp->head == op)
381 continue; 401 continue;
382 if (OB_MOVE_BLOCK(op, tmp) && !roll_ob(tmp,dir,pusher)) 402 if (OB_MOVE_BLOCK (op, tmp) && !roll_ob (tmp, dir, pusher))
383 return 0; 403 return 0;
384 } 404 }
385 } 405 }
386 if (try_fit (op, m, x, y)) 406 if (try_fit (op, m, x, y))
387 return 0; 407 return 0;
388 408
389 remove_ob(op); 409 op->remove ();
390 for(tmp=op; tmp!=NULL; tmp=tmp->more) 410 for (tmp = op; tmp != NULL; tmp = tmp->more)
391 tmp->x+=freearr_x[dir],tmp->y+=freearr_y[dir]; 411 tmp->x += freearr_x[dir], tmp->y += freearr_y[dir];
392 insert_ob_in_map(op,op->map,pusher,0); 412 insert_ob_in_map (op, op->map, pusher, 0);
393 return 1; 413 return 1;
394} 414}
395 415
396/* returns 1 if pushing invokes a attack, 0 when not */ 416/* returns 1 if pushing invokes a attack, 0 when not */
417int
397int push_ob(object *who, int dir, object *pusher) { 418push_ob (object *who, int dir, object *pusher)
419{
398 int str1, str2; 420 int str1, str2;
399 object *owner; 421 object *owner;
400 422
401 if (who->head != NULL) 423 if (who->head != NULL)
402 who = who->head; 424 who = who->head;
403 owner = get_owner(who); 425 owner = who->owner;
404 426
405 /* Wake up sleeping monsters that may be pushed */ 427 /* Wake up sleeping monsters that may be pushed */
406 CLEAR_FLAG(who,FLAG_SLEEP); 428 CLEAR_FLAG (who, FLAG_SLEEP);
407 429
408 /* player change place with his pets or summoned creature */ 430 /* player change place with his pets or summoned creature */
409 /* TODO: allow multi arch pushing. Can't be very difficult */ 431 /* TODO: allow multi arch pushing. Can't be very difficult */
410 if (who->more == NULL 432 if (who->more == NULL
411#ifdef COZY_SERVER 433#ifdef COZY_SERVER
412 && 434 && ((owner && owner->contr && pusher->contr && same_party (owner->contr->party, pusher->contr->party)) || owner == pusher)
413 (
414 (owner && owner->contr && pusher->contr
415 && same_party (owner->contr->party, pusher->contr->party))
416 || owner == pusher
417 )
418#else 435#else
419 && owner == pusher 436 && owner == pusher
420#endif 437#endif
421 ) { 438 )
422 int temp; 439 {
423 mapstruct *m; 440 int temp;
441 maptile *m;
424 442
425 remove_ob(who); 443 who->remove ();
426 remove_ob(pusher); 444 pusher->remove ();
427 temp = pusher->x; 445 temp = pusher->x;
428 pusher->x = who->x; 446 pusher->x = who->x;
429 who->x = temp; 447 who->x = temp;
430 448
431 temp = pusher->y; 449 temp = pusher->y;
432 pusher->y = who->y; 450 pusher->y = who->y;
433 who->y = temp; 451 who->y = temp;
434 452
435 m = pusher->map; 453 m = pusher->map;
436 pusher->map = who->map; 454 pusher->map = who->map;
437 who->map = m; 455 who->map = m;
438 456
439 insert_ob_in_map (who,who->map,pusher,0); 457 insert_ob_in_map (who, who->map, pusher, 0);
440 insert_ob_in_map (pusher,pusher->map,pusher,0); 458 insert_ob_in_map (pusher, pusher->map, pusher, 0);
441 return 0; 459 return 0;
442 } 460 }
443 461
444 462
445 /* 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 */
446 /* 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 */
447 /* we so often become an enemy of friendly monsters... */ 465 /* we so often become an enemy of friendly monsters... */
448 /* 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 */
449 467
450 if(owner != pusher && pusher->type == PLAYER && who->type != PLAYER && 468 if (owner != pusher && pusher->type == PLAYER && who->type != PLAYER &&
451 !QUERY_FLAG(who,FLAG_FRIENDLY)&& !QUERY_FLAG(who,FLAG_NEUTRAL)) { 469 !QUERY_FLAG (who, FLAG_FRIENDLY) && !QUERY_FLAG (who, FLAG_NEUTRAL))
470 {
452 if(pusher->contr->run_on) /* only when we run */ { 471 if (pusher->contr->run_on) /* only when we run */
453 new_draw_info_format(NDI_UNIQUE, 0, pusher, 472 {
454 "You start to attack %s !!",who->name); 473 new_draw_info_format (NDI_UNIQUE, 0, pusher, "You start to attack %s !!", &who->name);
455 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 */
456 who->enemy = pusher; 475 who->enemy = pusher;
457 return 1; 476 return 1;
458 } 477 }
459 else 478 else
460 { 479 {
461 new_draw_info_format(NDI_UNIQUE, 0, pusher, 480 new_draw_info_format (NDI_UNIQUE, 0, pusher, "You avoid attacking %s.", &who->name);
462 "You avoid attacking %s .",who->name); 481 }
463 }
464 } 482 }
465 483
466 /* 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. */
467 if(QUERY_FLAG(who,FLAG_STAND_STILL)) 485 if (QUERY_FLAG (who, FLAG_STAND_STILL))
468 {
469 new_draw_info_format(NDI_UNIQUE, 0, pusher,
470 "You can't push %s.",who->name);
471 return 0;
472 } 486 {
473 487 new_draw_info_format (NDI_UNIQUE, 0, pusher, "You can't push %s.", &who->name);
488 return 0;
489 }
490
474 /* This block is basically if you are pushing friendly but 491 /* This block is basically if you are pushing friendly but
475 * non pet creaturs. 492 * non pet creaturs.
476 * It basically does a random strength comparision to 493 * It basically does a random strength comparision to
477 * determine if you can push someone around. Note that 494 * determine if you can push someone around. Note that
478 * this pushes the other person away - its not a swap. 495 * this pushes the other person away - its not a swap.
479 */ 496 */
480 497
481 str1 = (who->stats.Str>0?who->stats.Str:who->level); 498 str1 = (who->stats.Str > 0 ? who->stats.Str : who->level);
482 str2 = (pusher->stats.Str>0?pusher->stats.Str:pusher->level); 499 str2 = (pusher->stats.Str > 0 ? pusher->stats.Str : pusher->level);
483 if(QUERY_FLAG(who,FLAG_WIZ) || 500 if (QUERY_FLAG (who, FLAG_WIZ) ||
484 random_roll(str1, str1/2+str1*2, who, PREFER_HIGH) >= 501 random_roll (str1, str1 / 2 + str1 * 2, who, PREFER_HIGH) >=
485 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))
486 !move_object(who,dir))
487 { 503 {
488 if (who ->type == PLAYER) { 504 if (who->type == PLAYER)
489 new_draw_info_format(NDI_UNIQUE, 0, who, 505 {
490 "%s tried to push you.",pusher->name); 506 new_draw_info_format (NDI_UNIQUE, 0, who, "%s tried to push you.", &pusher->name);
491 } 507 }
492 return 0; 508 return 0;
493 } 509 }
494 510
495 /* If we get here, the push succeeded. 511 /* If we get here, the push succeeded.
496 * Let everyone know the status. 512 * Let everyone know the status.
497 */ 513 */
498 if (who->type == PLAYER) { 514 if (who->type == PLAYER)
499 new_draw_info_format(NDI_UNIQUE, 0, who,
500 "%s pushed you.",pusher->name);
501 } 515 {
516 new_draw_info_format (NDI_UNIQUE, 0, who, "%s pushed you.", &pusher->name);
517 }
502 if (pusher->type == PLAYER) { 518 if (pusher->type == PLAYER)
503 new_draw_info_format(NDI_UNIQUE, 0, pusher,
504 "You pushed %s back.", who->name);
505 } 519 {
506 520 new_draw_info_format (NDI_UNIQUE, 0, pusher, "You pushed %s back.", &who->name);
521 }
522
507 return 1; 523 return 1;
508} 524}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines