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.5 by root, Tue Aug 29 17:32:19 2006 UTC vs.
Revision 1.13 by root, Thu Jan 4 16:19:32 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines