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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines