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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines