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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines