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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines