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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines