ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/time.C
(Generate patch)

Comparing deliantra/server/server/time.C (file contents):
Revision 1.5 by root, Tue Aug 29 07:34:01 2006 UTC vs.
Revision 1.6 by root, Tue Aug 29 08:01:38 2006 UTC

1/* 1/*
2 * static char *rcsid_time_c = 2 * static char *rcsid_time_c =
3 * "$Id: time.C,v 1.5 2006/08/29 07:34:01 root Exp $"; 3 * "$Id: time.C,v 1.6 2006/08/29 08:01:38 root Exp $";
4 */ 4 */
5 5
6/* 6/*
7 CrossFire, A Multiplayer game for X-windows 7 CrossFire, A Multiplayer game for X-windows
8 8
94 /* Code below assumes the generator is on a map, as it tries 94 /* Code below assumes the generator is on a map, as it tries
95 * to place the monster on the map. So if the generator 95 * to place the monster on the map. So if the generator
96 * isn't on a map, complain and exit. 96 * isn't on a map, complain and exit.
97 */ 97 */
98 if (gen->map == NULL) { 98 if (gen->map == NULL) {
99 //LOG(llevError,"Generator (%s) not on a map?\n", gen->name); 99 //LOG(llevError,"Generator (%s) not on a map?\n", gen->name);
100 return; 100 return;
101 } 101 }
102 /*First count numer of objects in inv*/ 102 /*First count numer of objects in inv*/
103 for (op=gen->inv;op;op=op->below) 103 for (op=gen->inv;op;op=op->below)
104 qty++; 104 qty++;
105 if (!qty){ 105 if (!qty){
128 int i; 128 int i;
129 object *op,*head=NULL,*prev=NULL; 129 object *op,*head=NULL,*prev=NULL;
130 archetype *at=gen->other_arch; 130 archetype *at=gen->other_arch;
131 131
132 if(gen->other_arch==NULL) { 132 if(gen->other_arch==NULL) {
133 //LOG(llevError,"Generator without other_arch: %s\n",gen->name); 133 //LOG(llevError,"Generator without other_arch: %s\n",gen->name);
134 return; 134 return;
135 } 135 }
136 /* Code below assumes the generator is on a map, as it tries 136 /* Code below assumes the generator is on a map, as it tries
137 * to place the monster on the map. So if the generator 137 * to place the monster on the map. So if the generator
138 * isn't on a map, complain and exit. 138 * isn't on a map, complain and exit.
139 */ 139 */
140 if (gen->map == NULL) { 140 if (gen->map == NULL) {
141 //LOG(llevError,"Generator (%s) not on a map?\n", gen->name); 141 //LOG(llevError,"Generator (%s) not on a map?\n", gen->name);
142 return; 142 return;
143 } 143 }
144 i=find_free_spot(&at->clone,gen->map,gen->x,gen->y,1,9); 144 i=find_free_spot(&at->clone,gen->map,gen->x,gen->y,1,9);
145 if (i==-1) return; 145 if (i==-1) return;
146 while(at!=NULL) { 146 while(at!=NULL) {
147 op=arch_to_object(at); 147 op=arch_to_object(at);
148 op->x=gen->x+freearr_x[i]+at->clone.x; 148 op->x=gen->x+freearr_x[i]+at->clone.x;
149 op->y=gen->y+freearr_y[i]+at->clone.y; 149 op->y=gen->y+freearr_y[i]+at->clone.y;
150 150
151 if(head!=NULL) 151 if(head!=NULL)
152 op->head=head,prev->more=op; 152 op->head=head,prev->more=op;
153 153
154 if (rndm(0, 9)) generate_artifact(op, gen->map->difficulty); 154 if (rndm(0, 9)) generate_artifact(op, gen->map->difficulty);
155 insert_ob_in_map(op,gen->map,gen,0); 155 insert_ob_in_map(op,gen->map,gen,0);
156 if (QUERY_FLAG(op, FLAG_FREED)) return; 156 if (QUERY_FLAG(op, FLAG_FREED)) return;
157 if(HAS_RANDOM_ITEMS(op)) 157 if(HAS_RANDOM_ITEMS(op))
158 create_treasure(op->randomitems,op,GT_APPLY, 158 create_treasure(op->randomitems,op,GT_APPLY,
159 gen->map->difficulty,0); 159 gen->map->difficulty,0);
160 if(head==NULL) 160 if(head==NULL)
161 head=op; 161 head=op;
162 prev=op; 162 prev=op;
163 at=at->more; 163 at=at->more;
164 } 164 }
165} 165}
166 166
167void generate_monster(object *gen) { 167void generate_monster(object *gen) {
168 168
177 177
178void remove_force(object *op) { 178void remove_force(object *op) {
179 if (--op->duration > 0) return; 179 if (--op->duration > 0) return;
180 180
181 switch (op->subtype) { 181 switch (op->subtype) {
182 case FORCE_CONFUSION: 182 case FORCE_CONFUSION:
183 if(op->env!=NULL) { 183 if(op->env!=NULL) {
184 CLEAR_FLAG(op->env, FLAG_CONFUSED); 184 CLEAR_FLAG(op->env, FLAG_CONFUSED);
185 new_draw_info(NDI_UNIQUE, 0,op->env, "You regain your senses.\n"); 185 new_draw_info(NDI_UNIQUE, 0,op->env, "You regain your senses.\n");
186 } 186 }
187 187
188 default: 188 default:
189 if(op->env!=NULL) { 189 if(op->env!=NULL) {
190 CLEAR_FLAG(op, FLAG_APPLIED); 190 CLEAR_FLAG(op, FLAG_APPLIED);
191 change_abil(op->env,op); 191 change_abil(op->env,op);
192 fix_player(op->env); 192 fix_player(op->env);
193 } 193 }
194 } 194 }
195 remove_ob(op); 195 remove_ob(op);
196 free_object(op); 196 free_object(op);
197} 197}
198 198
239 239
240void move_gate(object *op) { /* 1 = going down, 0 = goind up */ 240void move_gate(object *op) { /* 1 = going down, 0 = goind up */
241 object *tmp; 241 object *tmp;
242 242
243 if(op->stats.wc < 0 || (int)op->stats.wc >= NUM_ANIMATIONS(op)) { 243 if(op->stats.wc < 0 || (int)op->stats.wc >= NUM_ANIMATIONS(op)) {
244 LOG(llevError,"Gate error: animation was %d, max=%d\n",op->stats.wc, 244 LOG(llevError,"Gate error: animation was %d, max=%d\n",op->stats.wc,
245 NUM_ANIMATIONS(op)); 245 NUM_ANIMATIONS(op));
246 dump_object(op); 246 dump_object(op);
247 LOG(llevError,"%s\n",errmsg); 247 LOG(llevError,"%s\n",errmsg);
248 op->stats.wc=0; 248 op->stats.wc=0;
249 } 249 }
250 250
251 /* We're going down */ 251 /* We're going down */
252 if(op->value) { 252 if(op->value) {
253 if(--op->stats.wc<=0) { /* Reached bottom, let's stop */ 253 if(--op->stats.wc<=0) { /* Reached bottom, let's stop */
254 op->stats.wc=0; 254 op->stats.wc=0;
255 if(op->arch->clone.speed) 255 if(op->arch->clone.speed)
256 op->value=0; 256 op->value=0;
257 else { 257 else {
258 op->speed = 0; 258 op->speed = 0;
259 update_ob_speed(op); 259 update_ob_speed(op);
260 } 260 }
261 } 261 }
262 if((int)op->stats.wc < (NUM_ANIMATIONS(op)/2+1)) { 262 if((int)op->stats.wc < (NUM_ANIMATIONS(op)/2+1)) {
263 op->move_block = 0; 263 op->move_block = 0;
264 CLEAR_FLAG(op, FLAG_BLOCKSVIEW); 264 CLEAR_FLAG(op, FLAG_BLOCKSVIEW);
265 update_all_los(op->map, op->x, op->y); 265 update_all_los(op->map, op->x, op->y);
266 } 266 }
267 SET_ANIMATION(op, op->stats.wc); 267 SET_ANIMATION(op, op->stats.wc);
268 update_object(op,UP_OBJ_CHANGE); 268 update_object(op,UP_OBJ_CHANGE);
269 return; 269 return;
270 } 270 }
271 271
272 /* We're going up */ 272 /* We're going up */
273 273
274 /* First, lets see if we are already at the top */ 274 /* First, lets see if we are already at the top */
275 if((unsigned char) op->stats.wc==(NUM_ANIMATIONS(op)-1)) { 275 if((unsigned char) op->stats.wc==(NUM_ANIMATIONS(op)-1)) {
276 276
277 /* Check to make sure that only non pickable and non rollable 277 /* Check to make sure that only non pickable and non rollable
278 * objects are above the gate. If so, we finish closing the gate, 278 * objects are above the gate. If so, we finish closing the gate,
279 * otherwise, we fall through to the code below which should lower 279 * otherwise, we fall through to the code below which should lower
280 * the gate slightly. 280 * the gate slightly.
281 */ 281 */
282 282
283 for (tmp=op->above; tmp!=NULL; tmp=tmp->above) 283 for (tmp=op->above; tmp!=NULL; tmp=tmp->above)
284 if (!QUERY_FLAG(tmp, FLAG_NO_PICK) 284 if (!QUERY_FLAG(tmp, FLAG_NO_PICK)
285 || QUERY_FLAG(tmp, FLAG_CAN_ROLL) 285 || QUERY_FLAG(tmp, FLAG_CAN_ROLL)
286 || QUERY_FLAG(tmp, FLAG_ALIVE)) 286 || QUERY_FLAG(tmp, FLAG_ALIVE))
287 break; 287 break;
288 288
289 if (tmp==NULL) { 289 if (tmp==NULL) {
290 if(op->arch->clone.speed) 290 if(op->arch->clone.speed)
291 op->value=1; 291 op->value=1;
292 else { 292 else {
293 op->speed = 0; 293 op->speed = 0;
294 update_ob_speed(op); /* Reached top, let's stop */ 294 update_ob_speed(op); /* Reached top, let's stop */
295 } 295 }
296 return; 296 return;
297 } 297 }
298 } 298 }
299 299
300 if(op->stats.food) { /* The gate is going temporarily down */ 300 if(op->stats.food) { /* The gate is going temporarily down */
301 if(--op->stats.wc<=0) { /* Gone all the way down? */ 301 if(--op->stats.wc<=0) { /* Gone all the way down? */
302 op->stats.food=0; /* Then let's try again */ 302 op->stats.food=0; /* Then let's try again */
303 op->stats.wc=0; 303 op->stats.wc=0;
304 } 304 }
305 } else { /* The gate is still going up */ 305 } else { /* The gate is still going up */
306 op->stats.wc++; 306 op->stats.wc++;
307 307
308 if((int)op->stats.wc >= (NUM_ANIMATIONS(op))) 308 if((int)op->stats.wc >= (NUM_ANIMATIONS(op)))
309 op->stats.wc=(signed char)NUM_ANIMATIONS(op)-1; 309 op->stats.wc=(signed char)NUM_ANIMATIONS(op)-1;
310 310
311 /* If there is something on top of the gate, we try to roll it off. 311 /* If there is something on top of the gate, we try to roll it off.
312 * If a player/monster, we don't roll, we just hit them with damage 312 * If a player/monster, we don't roll, we just hit them with damage
313 */ 313 */
314 if((int)op->stats.wc >= NUM_ANIMATIONS(op)/2) { 314 if((int)op->stats.wc >= NUM_ANIMATIONS(op)/2) {
315 /* Halfway or further, check blocks */ 315 /* Halfway or further, check blocks */
316 /* First, get the top object on the square. */ 316 /* First, get the top object on the square. */
317 for(tmp=op->above;tmp!=NULL && tmp->above!=NULL;tmp=tmp->above); 317 for(tmp=op->above;tmp!=NULL && tmp->above!=NULL;tmp=tmp->above);
318 318
319 if(tmp!=NULL) { 319 if(tmp!=NULL) {
320 if(QUERY_FLAG(tmp, FLAG_ALIVE)) { 320 if(QUERY_FLAG(tmp, FLAG_ALIVE)) {
321 hit_player(tmp, random_roll(1, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1); 321 hit_player(tmp, random_roll(1, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1);
322 if(tmp->type==PLAYER) 322 if(tmp->type==PLAYER)
323 new_draw_info_format(NDI_UNIQUE, 0, tmp, 323 new_draw_info_format(NDI_UNIQUE, 0, tmp,
324 "You are crushed by the %s!",op->name); 324 "You are crushed by the %s!",op->name);
325 } else 325 } else
326 /* If the object is not alive, and the object either can 326 /* If the object is not alive, and the object either can
327 * be picked up or the object rolls, move the object 327 * be picked up or the object rolls, move the object
328 * off the gate. 328 * off the gate.
329 */ 329 */
330 if(!QUERY_FLAG(tmp, FLAG_ALIVE) 330 if(!QUERY_FLAG(tmp, FLAG_ALIVE)
331 && (!QUERY_FLAG(tmp, FLAG_NO_PICK) 331 && (!QUERY_FLAG(tmp, FLAG_NO_PICK)
332 ||QUERY_FLAG(tmp,FLAG_CAN_ROLL))) { 332 ||QUERY_FLAG(tmp,FLAG_CAN_ROLL))) {
333 /* If it has speed, it should move itself, otherwise: */ 333 /* If it has speed, it should move itself, otherwise: */
334 int i=find_free_spot(tmp,op->map,op->x,op->y,1,9); 334 int i=find_free_spot(tmp,op->map,op->x,op->y,1,9);
335 335
336 /* If there is a free spot, move the object someplace */ 336 /* If there is a free spot, move the object someplace */
337 if (i!=-1) { 337 if (i!=-1) {
338 remove_ob(tmp); 338 remove_ob(tmp);
339 tmp->x+=freearr_x[i],tmp->y+=freearr_y[i]; 339 tmp->x+=freearr_x[i],tmp->y+=freearr_y[i];
340 insert_ob_in_map(tmp,op->map,op,0); 340 insert_ob_in_map(tmp,op->map,op,0);
341 } 341 }
342 } 342 }
343 } 343 }
344 344
345 /* See if there is still anything blocking the gate */ 345 /* See if there is still anything blocking the gate */
346 for (tmp=op->above; tmp!=NULL; tmp=tmp->above) 346 for (tmp=op->above; tmp!=NULL; tmp=tmp->above)
347 if (!QUERY_FLAG(tmp, FLAG_NO_PICK) 347 if (!QUERY_FLAG(tmp, FLAG_NO_PICK)
348 || QUERY_FLAG(tmp, FLAG_CAN_ROLL) 348 || QUERY_FLAG(tmp, FLAG_CAN_ROLL)
349 || QUERY_FLAG(tmp, FLAG_ALIVE)) 349 || QUERY_FLAG(tmp, FLAG_ALIVE))
350 break; 350 break;
351 351
352 /* IF there is, start putting the gate down */ 352 /* IF there is, start putting the gate down */
353 if(tmp) { 353 if(tmp) {
354 op->stats.food=1; 354 op->stats.food=1;
355 } else { 355 } else {
356 op->move_block = MOVE_ALL; 356 op->move_block = MOVE_ALL;
357 if(!op->arch->clone.stats.ac) 357 if(!op->arch->clone.stats.ac)
358 SET_FLAG(op, FLAG_BLOCKSVIEW); 358 SET_FLAG(op, FLAG_BLOCKSVIEW);
359 update_all_los(op->map, op->x, op->y); 359 update_all_los(op->map, op->x, op->y);
360 } 360 }
361 } /* gate is halfway up */ 361 } /* gate is halfway up */
362 362
363 SET_ANIMATION(op, op->stats.wc); 363 SET_ANIMATION(op, op->stats.wc);
364 update_object(op,UP_OBJ_CHANGE); 364 update_object(op,UP_OBJ_CHANGE);
365 } /* gate is going up */ 365 } /* gate is going up */
366} 366}
367 367
368/* hp : how long door is open/closed 368/* hp : how long door is open/closed
369 * maxhp : initial value for hp 369 * maxhp : initial value for hp
380 return; 380 return;
381 } 381 }
382 if (--op->stats.hp <= 0) { /* keep gate down */ 382 if (--op->stats.hp <= 0) { /* keep gate down */
383 move_gate(op); 383 move_gate(op);
384 if (op->value != v) { /* ready ? */ 384 if (op->value != v) { /* ready ? */
385 op->speed = 0; 385 op->speed = 0;
386 update_ob_speed(op); 386 update_ob_speed(op);
387 } 387 }
388 } 388 }
389} 389}
390 390
391/* slaying: name of the thing the detector is to look for 391/* slaying: name of the thing the detector is to look for
401 int last = op->value; 401 int last = op->value;
402 int detected; 402 int detected;
403 detected = 0; 403 detected = 0;
404 404
405 for(tmp = get_map_ob(op->map,op->x,op->y);tmp!=NULL&&!detected;tmp=tmp->above) { 405 for(tmp = get_map_ob(op->map,op->x,op->y);tmp!=NULL&&!detected;tmp=tmp->above) {
406 object *tmp2; 406 object *tmp2;
407 if(op->stats.hp) { 407 if(op->stats.hp) {
408 for(tmp2= tmp->inv;tmp2;tmp2=tmp2->below) { 408 for(tmp2= tmp->inv;tmp2;tmp2=tmp2->below) {
409 if(op->slaying && !strcmp(op->slaying,tmp->name)) detected=1; 409 if(op->slaying && !strcmp(op->slaying,tmp->name)) detected=1;
410 if(tmp2->type==FORCE &&tmp2->slaying && !strcmp(tmp2->slaying,op->slaying)) detected=1; 410 if(tmp2->type==FORCE &&tmp2->slaying && !strcmp(tmp2->slaying,op->slaying)) detected=1;
411 } 411 }
412 } 412 }
413 if (op->slaying && !strcmp(op->slaying,tmp->name)) { 413 if (op->slaying && !strcmp(op->slaying,tmp->name)) {
414 detected = 1; 414 detected = 1;
415 } 415 }
416 else if (tmp->type==SPECIAL_KEY && tmp->slaying==op->slaying) 416 else if (tmp->type==SPECIAL_KEY && tmp->slaying==op->slaying)
417 detected=1; 417 detected=1;
418 } 418 }
419 419
420 /* the detector sets the button if detection is found */ 420 /* the detector sets the button if detection is found */
421 if(op->stats.sp == 1) { 421 if(op->stats.sp == 1) {
422 if(detected && last == 0) { 422 if(detected && last == 0) {
423 op->value = 1; 423 op->value = 1;
424 push_button(op); 424 push_button(op);
425 } 425 }
426 if(!detected && last == 1) { 426 if(!detected && last == 1) {
427 op->value = 0; 427 op->value = 0;
428 push_button(op); 428 push_button(op);
429 } 429 }
430 } 430 }
431 else { /* in this case, we unset buttons */ 431 else { /* in this case, we unset buttons */
432 if(detected && last == 1) { 432 if(detected && last == 1) {
433 op->value = 0; 433 op->value = 0;
434 push_button(op); 434 push_button(op);
435 } 435 }
436 if(!detected && last == 0) { 436 if(!detected && last == 0) {
437 op->value = 1; 437 op->value = 1;
438 push_button(op); 438 push_button(op);
439 } 439 }
440 } 440 }
441} 441}
442 442
443 443
444void animate_trigger (object *op) 444void animate_trigger (object *op)
454 454
455void move_hole(object *op) { /* 1 = opening, 0 = closing */ 455void move_hole(object *op) { /* 1 = opening, 0 = closing */
456 object *next,*tmp; 456 object *next,*tmp;
457 457
458 if(op->value) { /* We're opening */ 458 if(op->value) { /* We're opening */
459 if(--op->stats.wc<=0) { /* Opened, let's stop */ 459 if(--op->stats.wc<=0) { /* Opened, let's stop */
460 op->stats.wc=0; 460 op->stats.wc=0;
461 op->speed = 0; 461 op->speed = 0;
462 update_ob_speed(op); 462 update_ob_speed(op);
463 463
464 /* Hard coding this makes sense for holes I suppose */ 464 /* Hard coding this makes sense for holes I suppose */
465 op->move_on = MOVE_WALK; 465 op->move_on = MOVE_WALK;
466 for (tmp=op->above; tmp!=NULL; tmp=next) { 466 for (tmp=op->above; tmp!=NULL; tmp=next) {
467 next=tmp->above; 467 next=tmp->above;
468 move_apply(op,tmp,tmp); 468 move_apply(op,tmp,tmp);
469 } 469 }
470 } 470 }
471 SET_ANIMATION(op, op->stats.wc); 471 SET_ANIMATION(op, op->stats.wc);
472 update_object(op,UP_OBJ_FACE); 472 update_object(op,UP_OBJ_FACE);
473 return; 473 return;
474 } 474 }
475 /* We're closing */ 475 /* We're closing */
476 op->move_on = 0; 476 op->move_on = 0;
477 477
478 op->stats.wc++; 478 op->stats.wc++;
479 if((int)op->stats.wc >= NUM_ANIMATIONS(op)) 479 if((int)op->stats.wc >= NUM_ANIMATIONS(op))
480 op->stats.wc=NUM_ANIMATIONS(op)-1; 480 op->stats.wc=NUM_ANIMATIONS(op)-1;
481 SET_ANIMATION(op, op->stats.wc); 481 SET_ANIMATION(op, op->stats.wc);
482 update_object(op,UP_OBJ_FACE); 482 update_object(op,UP_OBJ_FACE);
483 if((unsigned char) op->stats.wc==(NUM_ANIMATIONS(op)-1)) { 483 if((unsigned char) op->stats.wc==(NUM_ANIMATIONS(op)-1)) {
484 op->speed = 0; 484 op->speed = 0;
485 update_ob_speed(op); /* closed, let's stop */ 485 update_ob_speed(op); /* closed, let's stop */
486 return; 486 return;
487 } 487 }
488} 488}
489 489
490 490
491/* stop_item() returns a pointer to the stopped object. The stopped object 491/* stop_item() returns a pointer to the stopped object. The stopped object
545 545
546 546
547object *fix_stopped_arrow (object *op) 547object *fix_stopped_arrow (object *op)
548{ 548{
549 if(rndm(0, 99) < op->stats.food) { 549 if(rndm(0, 99) < op->stats.food) {
550 /* Small chance of breaking */ 550 /* Small chance of breaking */
551 remove_ob (op); 551 remove_ob (op);
552 free_object(op); 552 free_object(op);
553 return NULL; 553 return NULL;
554 } 554 }
555 555
556 op->direction=0; 556 op->direction=0;
557 op->move_on=0; 557 op->move_on=0;
558 op->move_type=0; 558 op->move_type=0;
560 update_ob_speed(op); 560 update_ob_speed(op);
561 op->stats.wc = op->stats.sp; 561 op->stats.wc = op->stats.sp;
562 op->stats.dam= op->stats.hp; 562 op->stats.dam= op->stats.hp;
563 op->attacktype = op->stats.grace; 563 op->attacktype = op->stats.grace;
564 if (op->slaying != NULL) 564 if (op->slaying != NULL)
565 FREE_AND_CLEAR_STR(op->slaying); 565 FREE_AND_CLEAR_STR(op->slaying);
566 566
567 if (op->skill != NULL) 567 if (op->skill != NULL)
568 FREE_AND_CLEAR_STR(op->skill); 568 FREE_AND_CLEAR_STR(op->skill);
569 569
570 if (op->spellarg != NULL) { 570 if (op->spellarg != NULL) {
571 op->slaying = add_string(op->spellarg); 571 op->slaying = add_string(op->spellarg);
572 free(op->spellarg); 572 free(op->spellarg);
573 op->spellarg = NULL; 573 op->spellarg = NULL;
574 } else 574 } else
575 op->slaying = NULL; 575 op->slaying = NULL;
576 576
577 /* Reset these to zero, so that CAN_MERGE will work properly */ 577 /* Reset these to zero, so that CAN_MERGE will work properly */
578 op->spellarg = NULL; 578 op->spellarg = NULL;
579 op->stats.sp = 0; 579 op->stats.sp = 0;
580 op->stats.hp = 0; 580 op->stats.hp = 0;
598{ 598{
599 if (INVOKE_OBJECT (STOP, op)) 599 if (INVOKE_OBJECT (STOP, op))
600 return; 600 return;
601 601
602 if (op->inv) { 602 if (op->inv) {
603 object *payload = op->inv; 603 object *payload = op->inv;
604 remove_ob (payload); 604 remove_ob (payload);
605 clear_owner(payload); 605 clear_owner(payload);
606 insert_ob_in_map (payload, op->map, payload,0); 606 insert_ob_in_map (payload, op->map, payload,0);
607 remove_ob (op); 607 remove_ob (op);
608 free_object (op); 608 free_object (op);
609 } else { 609 } else {
610 op = fix_stopped_arrow (op); 610 op = fix_stopped_arrow (op);
611 if (op) 611 if (op)
612 merge_ob (op, NULL); 612 merge_ob (op, NULL);
613 } 613 }
621 sint16 new_x, new_y; 621 sint16 new_x, new_y;
622 int was_reflected, mflags; 622 int was_reflected, mflags;
623 mapstruct *m; 623 mapstruct *m;
624 624
625 if(op->map==NULL) { 625 if(op->map==NULL) {
626 LOG (llevError, "BUG: Arrow had no map.\n"); 626 LOG (llevError, "BUG: Arrow had no map.\n");
627 remove_ob(op); 627 remove_ob(op);
628 free_object(op); 628 free_object(op);
629 return; 629 return;
630 } 630 }
631 631
632 /* we need to stop thrown objects at some point. Like here. */ 632 /* we need to stop thrown objects at some point. Like here. */
633 if(op->type==THROWN_OBJ) { 633 if(op->type==THROWN_OBJ) {
634 /* If the object that the THROWN_OBJ encapsulates disappears, 634 /* If the object that the THROWN_OBJ encapsulates disappears,
635 * we need to have this object go away also - otherwise, you get 635 * we need to have this object go away also - otherwise, you get
636 * left over remnants on the map. Where this currently happens 636 * left over remnants on the map. Where this currently happens
637 * is if the player throws a bomb - the bomb explodes on its own, 637 * is if the player throws a bomb - the bomb explodes on its own,
638 * but this object sticks around. We could handle the cleanup in the 638 * but this object sticks around. We could handle the cleanup in the
639 * bomb code, but there are potential other cases where that could happen, 639 * bomb code, but there are potential other cases where that could happen,
640 * and it is easy enough to clean it up here. 640 * and it is easy enough to clean it up here.
641 */ 641 */
642 if (op->inv == NULL) { 642 if (op->inv == NULL) {
643 remove_ob(op); 643 remove_ob(op);
644 free_object(op); 644 free_object(op);
645 return; 645 return;
646 } 646 }
647 if(op->last_sp-- < 0) { 647 if(op->last_sp-- < 0) {
648 stop_arrow (op); 648 stop_arrow (op);
649 return; 649 return;
650 } 650 }
651 } 651 }
652 652
653 /* if the arrow is moving too slow.. stop it. 0.5 was chosen as lower 653 /* if the arrow is moving too slow.. stop it. 0.5 was chosen as lower
654 values look rediculous. */ 654 values look rediculous. */
655 if (op->speed < 0.5 && op->type==ARROW) { 655 if (op->speed < 0.5 && op->type==ARROW) {
656 stop_arrow(op); 656 stop_arrow(op);
657 return; 657 return;
658 } 658 }
659 659
660 /* Calculate target map square */ 660 /* Calculate target map square */
661 new_x = op->x + DIRX(op); 661 new_x = op->x + DIRX(op);
662 new_y = op->y + DIRY(op); 662 new_y = op->y + DIRY(op);
664 664
665 m = op->map; 665 m = op->map;
666 mflags = get_map_flags(m, &m, new_x, new_y, &new_x, &new_y); 666 mflags = get_map_flags(m, &m, new_x, new_y, &new_x, &new_y);
667 667
668 if (mflags & P_OUT_OF_MAP) { 668 if (mflags & P_OUT_OF_MAP) {
669 stop_arrow(op); 669 stop_arrow(op);
670 return; 670 return;
671 } 671 }
672 672
673 /* only need to look for living creatures if this flag is set */ 673 /* only need to look for living creatures if this flag is set */
674 if (mflags & P_IS_ALIVE) { 674 if (mflags & P_IS_ALIVE) {
675 for (tmp = get_map_ob(m, new_x, new_y); tmp != NULL; tmp=tmp->above) 675 for (tmp = get_map_ob(m, new_x, new_y); tmp != NULL; tmp=tmp->above)
676 if (QUERY_FLAG(tmp, FLAG_ALIVE)) break; 676 if (QUERY_FLAG(tmp, FLAG_ALIVE)) break;
677 677
678 678
679 /* Not really fair, but don't let monsters hit themselves with 679 /* Not really fair, but don't let monsters hit themselves with
680 * their own arrow - this can be because they fire it then 680 * their own arrow - this can be because they fire it then
681 * move into it. 681 * move into it.
682 */ 682 */
683 683
684 if (tmp != NULL && tmp != op->owner) { 684 if (tmp != NULL && tmp != op->owner) {
685 /* Found living object, but it is reflecting the missile. Update 685 /* Found living object, but it is reflecting the missile. Update
686 * as below. (Note that for living creatures there is a small 686 * as below. (Note that for living creatures there is a small
687 * chance that reflect_missile fails.) 687 * chance that reflect_missile fails.)
688 */ 688 */
689 689
690 if (QUERY_FLAG (tmp, FLAG_REFL_MISSILE) && 690 if (QUERY_FLAG (tmp, FLAG_REFL_MISSILE) &&
691 (rndm(0, 99)) < (90-op->level/10)) { 691 (rndm(0, 99)) < (90-op->level/10)) {
692 692
693 int number = op->face->number; 693 int number = op->face->number;
694 694
695 op->direction = absdir (op->direction + 4); 695 op->direction = absdir (op->direction + 4);
696 op->state = 0; 696 op->state = 0;
697 if (GET_ANIM_ID (op)) { 697 if (GET_ANIM_ID (op)) {
698 number += 4; 698 number += 4;
699 if (number > GET_ANIMATION (op, 8)) 699 if (number > GET_ANIMATION (op, 8))
700 number -= 8; 700 number -= 8;
701 op->face = &new_faces[number]; 701 op->face = &new_faces[number];
702 } 702 }
703 was_reflected = 1; /* skip normal movement calculations */ 703 was_reflected = 1; /* skip normal movement calculations */
704 } 704 }
705 else { 705 else {
706 /* Attack the object. */ 706 /* Attack the object. */
707 op = hit_with_arrow (op, tmp); 707 op = hit_with_arrow (op, tmp);
708 if (op == NULL) 708 if (op == NULL)
709 return; 709 return;
710 } 710 }
711 } /* if this is not hitting its owner */ 711 } /* if this is not hitting its owner */
712 } /* if there is something alive on this space */ 712 } /* if there is something alive on this space */
713 713
714 714
715 if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, new_x, new_y))) { 715 if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, new_x, new_y))) {
716 int retry=0; 716 int retry=0;
717 717
718 /* if the object doesn't reflect, stop the arrow from moving 718 /* if the object doesn't reflect, stop the arrow from moving
719 * note that this code will now catch cases where a monster is 719 * note that this code will now catch cases where a monster is
720 * on a wall but has reflecting - the arrow won't reflect. 720 * on a wall but has reflecting - the arrow won't reflect.
721 * Mapmakers shouldn't put monsters on top of wall in the first 721 * Mapmakers shouldn't put monsters on top of wall in the first
722 * place, so I don't consider that a problem. 722 * place, so I don't consider that a problem.
723 */ 723 */
724 if(!QUERY_FLAG(op, FLAG_REFLECTING) || !(rndm(0, 19))) { 724 if(!QUERY_FLAG(op, FLAG_REFLECTING) || !(rndm(0, 19))) {
725 stop_arrow (op); 725 stop_arrow (op);
726 return; 726 return;
727 } else { 727 } else {
728 /* If one of the major directions (n,s,e,w), just reverse it */ 728 /* If one of the major directions (n,s,e,w), just reverse it */
729 if(op->direction&1) { 729 if(op->direction&1) {
730 op->direction=absdir(op->direction+4); 730 op->direction=absdir(op->direction+4);
731 retry=1; 731 retry=1;
732 } 732 }
733 /* There were two blocks with identical code - 733 /* There were two blocks with identical code -
734 * use this retry here to make this one block 734 * use this retry here to make this one block
735 * that did the same thing. 735 * that did the same thing.
736 */ 736 */
737 while (retry<2) { 737 while (retry<2) {
738 int left, right, mflags; 738 int left, right, mflags;
739 mapstruct *m1; 739 mapstruct *m1;
740 sint16 x1, y1; 740 sint16 x1, y1;
741 741
742 retry++; 742 retry++;
743 743
744 /* Need to check for P_OUT_OF_MAP: if the arrow is tavelling 744 /* Need to check for P_OUT_OF_MAP: if the arrow is tavelling
745 * over a corner in a tiled map, it is possible that 745 * over a corner in a tiled map, it is possible that
746 * op->direction is within an adjacent map but either 746 * op->direction is within an adjacent map but either
747 * op->direction-1 or op->direction+1 does not exist. 747 * op->direction-1 or op->direction+1 does not exist.
748 */ 748 */
749 mflags = get_map_flags(op->map,&m1, op->x+freearr_x[absdir(op->direction-1)], 749 mflags = get_map_flags(op->map,&m1, op->x+freearr_x[absdir(op->direction-1)],
750 op->y+freearr_y[absdir(op->direction-1)], &x1, &y1); 750 op->y+freearr_y[absdir(op->direction-1)], &x1, &y1);
751 left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, (GET_MAP_MOVE_BLOCK(m1, x1, y1))); 751 left = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, (GET_MAP_MOVE_BLOCK(m1, x1, y1)));
752 752
753 mflags = get_map_flags(op->map,&m1, op->x+freearr_x[absdir(op->direction+1)], 753 mflags = get_map_flags(op->map,&m1, op->x+freearr_x[absdir(op->direction+1)],
754 op->y+freearr_y[absdir(op->direction+1)], &x1, &y1); 754 op->y+freearr_y[absdir(op->direction+1)], &x1, &y1);
755 right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, (GET_MAP_MOVE_BLOCK(m1, x1, y1))); 755 right = (mflags & P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, (GET_MAP_MOVE_BLOCK(m1, x1, y1)));
756 756
757 if(left==right) 757 if(left==right)
758 op->direction=absdir(op->direction+4); 758 op->direction=absdir(op->direction+4);
759 else if(left) 759 else if(left)
760 op->direction=absdir(op->direction+2); 760 op->direction=absdir(op->direction+2);
761 else if(right) 761 else if(right)
762 op->direction=absdir(op->direction-2); 762 op->direction=absdir(op->direction-2);
763 763
764 mflags = get_map_flags(op->map,&m1, op->x+DIRX(op),op->y+DIRY(op), &x1, &y1); 764 mflags = get_map_flags(op->map,&m1, op->x+DIRX(op),op->y+DIRY(op), &x1, &y1);
765 765
766 /* If this space is not out of the map and not blocked, valid space - 766 /* If this space is not out of the map and not blocked, valid space -
767 * don't need to retry again. 767 * don't need to retry again.
768 */ 768 */
769 if (!(mflags & P_OUT_OF_MAP) && 769 if (!(mflags & P_OUT_OF_MAP) &&
770 !OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m1, x1, y1))) break; 770 !OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m1, x1, y1))) break;
771 771
772 } 772 }
773 /* Couldn't find a direction to move the arrow to - just 773 /* Couldn't find a direction to move the arrow to - just
774 * top it from moving. 774 * top it from moving.
775 */ 775 */
776 if (retry==2) { 776 if (retry==2) {
777 stop_arrow (op); 777 stop_arrow (op);
778 return; 778 return;
779 } 779 }
780 /* update object image for new facing */ 780 /* update object image for new facing */
781 /* many thrown objects *don't* have more than one face */ 781 /* many thrown objects *don't* have more than one face */
782 if(GET_ANIM_ID(op)) 782 if(GET_ANIM_ID(op))
783 SET_ANIMATION(op, op->direction); 783 SET_ANIMATION(op, op->direction);
784 } /* object is reflected */ 784 } /* object is reflected */
785 } /* object ran into a wall */ 785 } /* object ran into a wall */
786 786
787 /* Move the arrow. */ 787 /* Move the arrow. */
788 remove_ob (op); 788 remove_ob (op);
789 op->x = new_x; 789 op->x = new_x;
809 return; 809 return;
810 } 810 }
811 811
812 /* In non-living items only change when food value is 0 */ 812 /* In non-living items only change when food value is 0 */
813 if(!QUERY_FLAG(op,FLAG_ALIVE)) { 813 if(!QUERY_FLAG(op,FLAG_ALIVE)) {
814 if(op->stats.food-- > 0) return; 814 if(op->stats.food-- > 0) return;
815 else op->stats.food=1; /* so 1 other_arch is made */ 815 else op->stats.food=1; /* so 1 other_arch is made */
816 } 816 }
817 env=op->env; 817 env=op->env;
818 remove_ob(op); 818 remove_ob(op);
819 for(i=0;i<NROFNEWOBJS(op);i++) { 819 for(i=0;i<NROFNEWOBJS(op);i++) {
820 tmp=arch_to_object(op->other_arch); 820 tmp=arch_to_object(op->other_arch);
821 if (op->type == LAMP) 821 if (op->type == LAMP)
822 tmp->stats.food = op->stats.food-1; 822 tmp->stats.food = op->stats.food-1;
823 tmp->stats.hp=op->stats.hp; /* The only variable it keeps. */ 823 tmp->stats.hp=op->stats.hp; /* The only variable it keeps. */
824 if(env) { 824 if(env) {
825 tmp->x=env->x,tmp->y=env->y; 825 tmp->x=env->x,tmp->y=env->y;
826 tmp=insert_ob_in_ob(tmp,env); 826 tmp=insert_ob_in_ob(tmp,env);
827 /* If this object is the players inventory, we need to tell the 827 /* If this object is the players inventory, we need to tell the
828 * client of the change. Insert_ob_in_map takes care of the 828 * client of the change. Insert_ob_in_map takes care of the
829 * updating the client, so we don't need to do that below. 829 * updating the client, so we don't need to do that below.
830 */ 830 */
831 if ((pl=is_player_inv(env))!=NULL) { 831 if ((pl=is_player_inv(env))!=NULL) {
832 esrv_del_item(pl->contr, op->count); 832 esrv_del_item(pl->contr, op->count);
833 esrv_send_item(pl, tmp); 833 esrv_send_item(pl, tmp);
834 } 834 }
835 } else { 835 } else {
836 j=find_first_free_spot(tmp,op->map,op->x,op->y); 836 j=find_first_free_spot(tmp,op->map,op->x,op->y);
837 if (j==-1) /* No free spot */ 837 if (j==-1) /* No free spot */
838 free_object(tmp); 838 free_object(tmp);
839 else { 839 else {
840 tmp->x=op->x+freearr_x[j],tmp->y=op->y+freearr_y[j]; 840 tmp->x=op->x+freearr_x[j],tmp->y=op->y+freearr_y[j];
841 insert_ob_in_map(tmp,op->map,op,0); 841 insert_ob_in_map(tmp,op->map,op,0);
842 } 842 }
843 } 843 }
844 } 844 }
845 free_object(op); 845 free_object(op);
846} 846}
847 847
858 if (op->more && FABS(op->more->speed)<MIN_ACTIVE_SPEED) move_teleporter(op->more); 858 if (op->more && FABS(op->more->speed)<MIN_ACTIVE_SPEED) move_teleporter(op->more);
859 859
860 if (op->head) head=op->head; 860 if (op->head) head=op->head;
861 861
862 for (tmp=op->above; tmp!=NULL; tmp=tmp->above) 862 for (tmp=op->above; tmp!=NULL; tmp=tmp->above)
863 if (!QUERY_FLAG(tmp, FLAG_IS_FLOOR)) break; 863 if (!QUERY_FLAG(tmp, FLAG_IS_FLOOR)) break;
864 864
865 /* If nothing above us to move, nothing to do */ 865 /* If nothing above us to move, nothing to do */
866 if (!tmp || QUERY_FLAG(tmp, FLAG_WIZPASS)) return; 866 if (!tmp || QUERY_FLAG(tmp, FLAG_WIZPASS)) return;
867 867
868 if(EXIT_PATH(head)) { 868 if(EXIT_PATH(head)) {
869 if(tmp->type==PLAYER) { 869 if(tmp->type==PLAYER) {
870 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp))) 870 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp)))
871 return; 871 return;
872 872
873 enter_exit(tmp, head); 873 enter_exit(tmp, head);
874 } 874 }
875 else 875 else
876 /* Currently only players can transfer maps */ 876 /* Currently only players can transfer maps */
877 return; 877 return;
878 } 878 }
879 else if(EXIT_X(head)||EXIT_Y(head)) { 879 else if(EXIT_X(head)||EXIT_Y(head)) {
880 if (out_of_map(head->map, EXIT_X(head), EXIT_Y(head))) { 880 if (out_of_map(head->map, EXIT_X(head), EXIT_Y(head))) {
881 LOG(llevError, "Removed illegal teleporter.\n"); 881 LOG(llevError, "Removed illegal teleporter.\n");
882 remove_ob(head); 882 remove_ob(head);
883 free_object(head); 883 free_object(head);
884 return; 884 return;
885 } 885 }
886 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp))) 886 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp)))
887 return; 887 return;
888 transfer_ob(tmp,EXIT_X(head),EXIT_Y(head),0,head); 888 transfer_ob(tmp,EXIT_X(head),EXIT_Y(head),0,head);
889 } 889 }
890 else { 890 else {
891 /* Random teleporter */ 891 /* Random teleporter */
892 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp))) 892 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp)))
893 return; 893 return;
894 teleport(head, TELEPORTER, tmp); 894 teleport(head, TELEPORTER, tmp);
895 } 895 }
896} 896}
897 897
898 898
899/* This object will teleport someone to a different map 899/* This object will teleport someone to a different map
913 * needs to be on top. 913 * needs to be on top.
914 */ 914 */
915 if(op->above->type==PLAYER) { 915 if(op->above->type==PLAYER) {
916 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (player))) 916 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (player)))
917 return; 917 return;
918 player=op->above; 918 player=op->above;
919 for(walk=op->inv;walk!=NULL;walk=walk->below) 919 for(walk=op->inv;walk!=NULL;walk=walk->below)
920 apply_changes_to_player(player,walk); 920 apply_changes_to_player(player,walk);
921 921
922 fix_player(player); 922 fix_player(player);
923 esrv_send_inventory(op->above,op->above); 923 esrv_send_inventory(op->above,op->above);
924 esrv_update_item(UPD_FACE, op->above, op->above); 924 esrv_update_item(UPD_FACE, op->above, op->above);
925 925
926 /* update players death & WoR home-position */ 926 /* update players death & WoR home-position */
927 sscanf(EXIT_PATH(op), "%c", &c); 927 sscanf(EXIT_PATH(op), "%c", &c);
928 if (c == '/') { 928 if (c == '/') {
929 strcpy(player->contr->savebed_map, EXIT_PATH(op)); 929 strcpy(player->contr->savebed_map, EXIT_PATH(op));
930 player->contr->bed_x = EXIT_X(op); 930 player->contr->bed_x = EXIT_X(op);
931 player->contr->bed_y = EXIT_Y(op); 931 player->contr->bed_y = EXIT_Y(op);
932 } 932 }
933 else 933 else
934 LOG(llevDebug, 934 LOG(llevDebug,
935 "WARNING: destination '%s' in player_changer must be an absolute path!\n", 935 "WARNING: destination '%s' in player_changer must be an absolute path!\n",
936 EXIT_PATH(op)); 936 EXIT_PATH(op));
937 937
938 enter_exit(op->above,op); 938 enter_exit(op->above,op);
939 save_player(player, 1); 939 save_player(player, 1);
940 } 940 }
941} 941}
942 942
943/* firewalls fire other spells. 943/* firewalls fire other spells.
944 * The direction of the wall is stored in op->stats.sp. 944 * The direction of the wall is stored in op->stats.sp.
946 */ 946 */
947void move_firewall(object *op) { 947void move_firewall(object *op) {
948 object *spell; 948 object *spell;
949 949
950 if ( ! op->map) 950 if ( ! op->map)
951 return; /* dm has created a firewall in his inventory */ 951 return; /* dm has created a firewall in his inventory */
952 952
953 spell = op->inv; 953 spell = op->inv;
954 if (!spell || spell->type != SPELL) spell=&op->other_arch->clone; 954 if (!spell || spell->type != SPELL) spell=&op->other_arch->clone;
955 if (!spell) { 955 if (!spell) {
956 LOG(llevError,"move_firewall: no spell specified (%s, %s, %d, %d)\n", 956 LOG(llevError,"move_firewall: no spell specified (%s, %s, %d, %d)\n",
957 op->name, op->map->name, op->x, op->y); 957 op->name, op->map->name, op->x, op->y);
958 return; 958 return;
959 } 959 }
960 960
961 cast_spell(op,op,op->stats.sp?op->stats.sp:rndm(1, 8),spell, NULL); 961 cast_spell(op,op,op->stats.sp?op->stats.sp:rndm(1, 8),spell, NULL);
962} 962}
963 963
979 979
980 /* Determine direction now for random movers so we do the right thing */ 980 /* Determine direction now for random movers so we do the right thing */
981 if (!dir) dir=rndm(1, 8); 981 if (!dir) dir=rndm(1, 8);
982 982
983 for(victim=get_map_ob(op->map,op->x,op->y); victim !=NULL; victim=victim->above) { 983 for(victim=get_map_ob(op->map,op->x,op->y); victim !=NULL; victim=victim->above) {
984 if(QUERY_FLAG(victim, FLAG_ALIVE) && !QUERY_FLAG(victim, FLAG_WIZPASS) && 984 if(QUERY_FLAG(victim, FLAG_ALIVE) && !QUERY_FLAG(victim, FLAG_WIZPASS) &&
985 (victim->move_type & op->move_type || !victim->move_type)) { 985 (victim->move_type & op->move_type || !victim->move_type)) {
986 986
987 if (victim->head) victim = victim->head; 987 if (victim->head) victim = victim->head;
988 988
989 if(QUERY_FLAG(op,FLAG_LIFESAVE)&&op->stats.hp--<0) { 989 if(QUERY_FLAG(op,FLAG_LIFESAVE)&&op->stats.hp--<0) {
990 remove_ob(op); 990 remove_ob(op);
991 free_object(op); 991 free_object(op);
992 return; 992 return;
993 } 993 }
994 nx = op->x+freearr_x[dir]; 994 nx = op->x+freearr_x[dir];
995 ny = op->y+freearr_y[dir]; 995 ny = op->y+freearr_y[dir];
996 m = op->map; 996 m = op->map;
997 if (get_map_flags(m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) { 997 if (get_map_flags(m, &m, nx, ny, &nx, &ny) & P_OUT_OF_MAP) {
998 LOG(llevError,"move_player_mover: Trying to push player off the map! map=%s (%d, %d)\n", 998 LOG(llevError,"move_player_mover: Trying to push player off the map! map=%s (%d, %d)\n",
999 m->path, op->x, op->y); 999 m->path, op->x, op->y);
1000 return ; 1000 return ;
1001 } 1001 }
1002 1002
1003 if (should_director_abort(op, victim)) return ; 1003 if (should_director_abort(op, victim)) return ;
1004 1004
1005 for(nextmover=get_map_ob(m,nx, ny); nextmover !=NULL; nextmover=nextmover->above) { 1005 for(nextmover=get_map_ob(m,nx, ny); nextmover !=NULL; nextmover=nextmover->above) {
1006 if(nextmover->type == PLAYERMOVER) 1006 if(nextmover->type == PLAYERMOVER)
1007 nextmover->speed_left=-.99; 1007 nextmover->speed_left=-.99;
1008 if(QUERY_FLAG(nextmover,FLAG_ALIVE)) { 1008 if(QUERY_FLAG(nextmover,FLAG_ALIVE)) {
1009 op->speed_left=-1.1; /* wait until the next thing gets out of the way */ 1009 op->speed_left=-1.1; /* wait until the next thing gets out of the way */
1010 } 1010 }
1011 } 1011 }
1012 1012
1013 if(victim->type==PLAYER) { 1013 if(victim->type==PLAYER) {
1014 /* only level >=1 movers move people */ 1014 /* only level >=1 movers move people */
1015 if(op->level) { 1015 if(op->level) {
1016 /* Following is a bit of hack. We need to make sure it 1016 /* Following is a bit of hack. We need to make sure it
1017 * is cleared, otherwise the player will get stuck in 1017 * is cleared, otherwise the player will get stuck in
1018 * place. This can happen if the player used a spell to 1018 * place. This can happen if the player used a spell to
1019 * get to this space. 1019 * get to this space.
1020 */ 1020 */
1021 victim->contr->fire_on=0; 1021 victim->contr->fire_on=0;
1022 victim->speed_left=-FABS(victim->speed); 1022 victim->speed_left=-FABS(victim->speed);
1023 move_player(victim, dir); 1023 move_player(victim, dir);
1024 } 1024 }
1025 else return; 1025 else return;
1026 } 1026 }
1027 else move_object(victim,dir); 1027 else move_object(victim,dir);
1028 1028
1029 if(!op->stats.maxsp&&op->attacktype) op->stats.maxsp=2; 1029 if(!op->stats.maxsp&&op->attacktype) op->stats.maxsp=2;
1030 1030
1031 if(op->attacktype) { /* flag to paralyze the player */ 1031 if(op->attacktype) { /* flag to paralyze the player */
1032 1032
1033 victim->speed_left= -FABS(op->stats.maxsp*victim->speed/op->speed); 1033 victim->speed_left= -FABS(op->stats.maxsp*victim->speed/op->speed);
1034 /* Not sure why, but for some chars on metalforge, they 1034 /* Not sure why, but for some chars on metalforge, they
1035 * would sometimes get -inf speed_left, and from the 1035 * would sometimes get -inf speed_left, and from the
1036 * description, it could only happen here, so just put 1036 * description, it could only happen here, so just put
1037 * a lower sanity limit. My only guess is that the 1037 * a lower sanity limit. My only guess is that the
1038 * mover has 0 speed. 1038 * mover has 0 speed.
1039 */ 1039 */
1040 if (victim->speed_left < -5.0) victim->speed_left=-5.0; 1040 if (victim->speed_left < -5.0) victim->speed_left=-5.0;
1041 } 1041 }
1042 } 1042 }
1043 } 1043 }
1044} 1044}
1045 1045
1046/* 1046/*
1047 * Will duplicate a specified object placed on top of it. 1047 * Will duplicate a specified object placed on top of it.
1057 LOG(llevInfo, "Duplicator with no other_arch! %d %d %s\n", op->x, op->y, op->map ? op->map->path : "nullmap"); 1057 LOG(llevInfo, "Duplicator with no other_arch! %d %d %s\n", op->x, op->y, op->map ? op->map->path : "nullmap");
1058 return; 1058 return;
1059 } 1059 }
1060 1060
1061 if (op->above == NULL) 1061 if (op->above == NULL)
1062 return; 1062 return;
1063 for (tmp=op->above; tmp != NULL; tmp=tmp->above) { 1063 for (tmp=op->above; tmp != NULL; tmp=tmp->above) {
1064 if (strcmp(op->other_arch->name, tmp->arch->name) == 0) { 1064 if (strcmp(op->other_arch->name, tmp->arch->name) == 0) {
1065 if (op->level <= 0) { 1065 if (op->level <= 0) {
1066 remove_ob(tmp); 1066 remove_ob(tmp);
1067 free_object(tmp); 1067 free_object(tmp);
1068 } else { 1068 } else {
1069 uint64 new_nrof = (uint64)tmp->nrof*op->level; 1069 uint64 new_nrof = (uint64)tmp->nrof*op->level;
1070 if (new_nrof >= 1UL<<31) 1070 if (new_nrof >= 1UL<<31)
1071 new_nrof = 1UL<<31; 1071 new_nrof = 1UL<<31;
1072 tmp->nrof = new_nrof; 1072 tmp->nrof = new_nrof;
1073 } 1073 }
1074 break; 1074 break;
1075 } 1075 }
1076 } 1076 }
1077} 1077}
1078 1078
1079/* move_creator (by peterm) 1079/* move_creator (by peterm)
1080 * it has the creator object create it's other_arch right on top of it. 1080 * it has the creator object create it's other_arch right on top of it.
1092 1092
1093void move_creator(object *creator) { 1093void move_creator(object *creator) {
1094 object *new_ob; 1094 object *new_ob;
1095 1095
1096 if(!QUERY_FLAG(creator, FLAG_LIFESAVE) && --creator->stats.hp < 0) { 1096 if(!QUERY_FLAG(creator, FLAG_LIFESAVE) && --creator->stats.hp < 0) {
1097 creator->stats.hp=-1; 1097 creator->stats.hp=-1;
1098 return; 1098 return;
1099 } 1099 }
1100 1100
1101 if (creator->inv != NULL) { 1101 if (creator->inv != NULL) {
1102 object *ob; 1102 object *ob;
1103 int i; 1103 int i;
1104 object *ob_to_copy; 1104 object *ob_to_copy;
1105 1105
1106 /* select random object from inventory to copy */ 1106 /* select random object from inventory to copy */
1107 ob_to_copy = creator->inv; 1107 ob_to_copy = creator->inv;
1108 for (ob = creator->inv->below, i = 1; ob != NULL; ob = ob->below, i++) { 1108 for (ob = creator->inv->below, i = 1; ob != NULL; ob = ob->below, i++) {
1109 if (rndm(0, i) == 0) { 1109 if (rndm(0, i) == 0) {
1110 ob_to_copy = ob; 1110 ob_to_copy = ob;
1111 } 1111 }
1112 } 1112 }
1113 new_ob = object_create_clone(ob_to_copy); 1113 new_ob = object_create_clone(ob_to_copy);
1114 CLEAR_FLAG(new_ob, FLAG_IS_A_TEMPLATE); 1114 CLEAR_FLAG(new_ob, FLAG_IS_A_TEMPLATE);
1115 unflag_inv(new_ob, FLAG_IS_A_TEMPLATE); 1115 unflag_inv(new_ob, FLAG_IS_A_TEMPLATE);
1116 } else { 1116 } else {
1117 if (creator->other_arch == NULL) { 1117 if (creator->other_arch == NULL) {
1118 LOG(llevError,"move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n", creator->name ? creator->name : "(null)", creator->map->path, creator->x, creator->y); 1118 LOG(llevError,"move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n", creator->name ? creator->name : "(null)", creator->map->path, creator->x, creator->y);
1119 return; 1119 return;
1120 } 1120 }
1121 1121
1122 new_ob = object_create_arch(creator->other_arch); 1122 new_ob = object_create_arch(creator->other_arch);
1123 fix_generated_item(new_ob, creator, 0, 0, GT_MINIMAL); 1123 fix_generated_item(new_ob, creator, 0, 0, GT_MINIMAL);
1124 } 1124 }
1125 1125
1126 /* Make sure this multipart object fits */ 1126 /* Make sure this multipart object fits */
1127 if (new_ob->arch->more && ob_blocked(new_ob, creator->map, creator->x, creator->y)) { 1127 if (new_ob->arch->more && ob_blocked(new_ob, creator->map, creator->x, creator->y)) {
1128 free_object(new_ob); 1128 free_object(new_ob);
1129 return; 1129 return;
1130 } 1130 }
1131 1131
1132 insert_ob_in_map_at(new_ob, creator->map, creator, 0, creator->x, creator->y); 1132 insert_ob_in_map_at(new_ob, creator->map, creator, 0, creator->x, creator->y);
1133 if (QUERY_FLAG(new_ob, FLAG_FREED)) 1133 if (QUERY_FLAG(new_ob, FLAG_FREED))
1134 return; 1134 return;
1135 1135
1136 if (creator->slaying) { 1136 if (creator->slaying) {
1137 FREE_AND_COPY(new_ob->name, creator->slaying); 1137 FREE_AND_COPY(new_ob->name, creator->slaying);
1138 FREE_AND_COPY(new_ob->title, creator->slaying); 1138 FREE_AND_COPY(new_ob->title, creator->slaying);
1139 } 1139 }
1140} 1140}
1141 1141
1142/* move_marker --peterm@soda.csua.berkeley.edu 1142/* move_marker --peterm@soda.csua.berkeley.edu
1143 when moved, a marker will search for a player sitting above 1143 when moved, a marker will search for a player sitting above
1150 1150
1151void move_marker(object *op) { 1151void move_marker(object *op) {
1152 object *tmp,*tmp2; 1152 object *tmp,*tmp2;
1153 1153
1154 for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above) { 1154 for(tmp=get_map_ob(op->map,op->x,op->y);tmp!=NULL;tmp=tmp->above) {
1155 if(tmp->type == PLAYER) { /* we've got someone to MARK */ 1155 if(tmp->type == PLAYER) { /* we've got someone to MARK */
1156 1156
1157 if ( quest_on_activate(op, tmp->contr) ) 1157 if ( quest_on_activate(op, tmp->contr) )
1158 return; 1158 return;
1159 1159
1160 /* remove an old force with a slaying field == op->name */ 1160 /* remove an old force with a slaying field == op->name */
1161 for(tmp2=tmp->inv;tmp2 !=NULL; tmp2=tmp2->below) { 1161 for(tmp2=tmp->inv;tmp2 !=NULL; tmp2=tmp2->below) {
1162 if(tmp2->type == FORCE && tmp2->slaying && !strcmp(tmp2->slaying,op->name)) break; 1162 if(tmp2->type == FORCE && tmp2->slaying && !strcmp(tmp2->slaying,op->name)) break;
1163 } 1163 }
1164 1164
1165 if(tmp2) { 1165 if(tmp2) {
1166 remove_ob(tmp2); 1166 remove_ob(tmp2);
1167 free_object(tmp2); 1167 free_object(tmp2);
1168 } 1168 }
1169 1169
1170 /* cycle through his inventory to look for the MARK we want to 1170 /* cycle through his inventory to look for the MARK we want to
1171 * place 1171 * place
1172 */ 1172 */
1173 for(tmp2=tmp->inv;tmp2 !=NULL; tmp2=tmp2->below) { 1173 for(tmp2=tmp->inv;tmp2 !=NULL; tmp2=tmp2->below) {
1174 if(tmp2->type == FORCE && tmp2->slaying && !strcmp(tmp2->slaying,op->slaying)) break; 1174 if(tmp2->type == FORCE && tmp2->slaying && !strcmp(tmp2->slaying,op->slaying)) break;
1175 } 1175 }
1176 1176
1177 /* if we didn't find our own MARK */ 1177 /* if we didn't find our own MARK */
1178 if(tmp2==NULL) { 1178 if(tmp2==NULL) {
1179 object *force = get_archetype(FORCE_NAME); 1179 object *force = get_archetype(FORCE_NAME);
1180 1180
1181 force->speed = 0; 1181 force->speed = 0;
1182 if(op->stats.food) { 1182 if(op->stats.food) {
1183 force->speed = 0.01; 1183 force->speed = 0.01;
1184 force->speed_left = -op->stats.food; 1184 force->speed_left = -op->stats.food;
1185 } 1185 }
1186 update_ob_speed (force); 1186 update_ob_speed (force);
1187 /* put in the lock code */ 1187 /* put in the lock code */
1188 force->slaying = add_string(op->slaying); 1188 force->slaying = add_string(op->slaying);
1189 1189
1190 if ( op->lore ) 1190 if ( op->lore )
1191 force->lore = add_string( op->lore ); 1191 force->lore = add_string( op->lore );
1192 1192
1193 insert_ob_in_ob(force,tmp); 1193 insert_ob_in_ob(force,tmp);
1194 if(op->msg) 1194 if(op->msg)
1195 new_draw_info(NDI_UNIQUE|NDI_NAVY,0,tmp,op->msg); 1195 new_draw_info(NDI_UNIQUE|NDI_NAVY,0,tmp,op->msg);
1196 1196
1197 if(op->stats.hp > 0) { 1197 if(op->stats.hp > 0) {
1198 op->stats.hp--; 1198 op->stats.hp--;
1199 if(op->stats.hp==0) { 1199 if(op->stats.hp==0) {
1200 /* marker expires--granted mark number limit */ 1200 /* marker expires--granted mark number limit */
1201 remove_ob(op); 1201 remove_ob(op);
1202 free_object(op); 1202 free_object(op);
1203 return; 1203 return;
1204 } 1204 }
1205 } 1205 }
1206 } /* if tmp2 == NULL */ 1206 } /* if tmp2 == NULL */
1207 } /* if tmp->type == PLAYER */ 1207 } /* if tmp->type == PLAYER */
1208 } /* For all objects on this space */ 1208 } /* For all objects on this space */
1209} 1209}
1210 1210
1211int process_object(object *op) { 1211int process_object(object *op) {
1212 if (QUERY_FLAG(op, FLAG_IS_A_TEMPLATE)) 1212 if (QUERY_FLAG(op, FLAG_IS_A_TEMPLATE))
1213 return 0; 1213 return 0;
1214 1214
1215 if (INVOKE_OBJECT (TICK, op)) 1215 if (INVOKE_OBJECT (TICK, op))
1216 return 0; 1216 return 0;
1217 1217
1218 if(QUERY_FLAG(op, FLAG_MONSTER)) 1218 if(QUERY_FLAG(op, FLAG_MONSTER))
1219 if(move_monster(op) || QUERY_FLAG(op, FLAG_FREED)) 1219 if(move_monster(op) || QUERY_FLAG(op, FLAG_FREED))
1220 return 1; 1220 return 1;
1221 1221
1222 if(QUERY_FLAG(op, FLAG_ANIMATE) && op->anim_speed==0) { 1222 if(QUERY_FLAG(op, FLAG_ANIMATE) && op->anim_speed==0) {
1223 if (op->type == PLAYER) 1223 if (op->type == PLAYER)
1224 animate_object(op, op->facing); 1224 animate_object(op, op->facing);
1225 else 1225 else
1226 animate_object(op, op->direction); 1226 animate_object(op, op->direction);
1227 1227
1228 if (QUERY_FLAG(op, FLAG_SEE_ANYWHERE)) 1228 if (QUERY_FLAG(op, FLAG_SEE_ANYWHERE))
1229 make_sure_seen(op); 1229 make_sure_seen(op);
1230 } 1230 }
1231 if(QUERY_FLAG(op, FLAG_CHANGING)&&!op->state) { 1231 if(QUERY_FLAG(op, FLAG_CHANGING)&&!op->state) {
1232 change_object(op); 1232 change_object(op);
1233 return 1; 1233 return 1;
1234 } 1234 }
1235 if(QUERY_FLAG(op, FLAG_GENERATOR)&&!QUERY_FLAG(op, FLAG_FRIENDLY)) 1235 if(QUERY_FLAG(op, FLAG_GENERATOR)&&!QUERY_FLAG(op, FLAG_FRIENDLY))
1236 generate_monster(op); 1236 generate_monster(op);
1237 1237
1238 if(QUERY_FLAG(op, FLAG_IS_USED_UP)&&--op->stats.food<=0) { 1238 if(QUERY_FLAG(op, FLAG_IS_USED_UP)&&--op->stats.food<=0) {
1239 if(QUERY_FLAG(op, FLAG_APPLIED)) 1239 if(QUERY_FLAG(op, FLAG_APPLIED))
1240 remove_force(op); 1240 remove_force(op);
1241 else { 1241 else {
1242 /* IF necessary, delete the item from the players inventory */ 1242 /* IF necessary, delete the item from the players inventory */
1243 object *pl=is_player_inv(op); 1243 object *pl=is_player_inv(op);
1244 if (pl) 1244 if (pl)
1245 esrv_del_item(pl->contr, op->count); 1245 esrv_del_item(pl->contr, op->count);
1246 remove_ob(op); 1246 remove_ob(op);
1247 if (QUERY_FLAG(op, FLAG_SEE_ANYWHERE)) 1247 if (QUERY_FLAG(op, FLAG_SEE_ANYWHERE))
1248 make_sure_not_seen(op); 1248 make_sure_not_seen(op);
1249 free_object(op); 1249 free_object(op);
1250 } 1250 }
1251 return 1; 1251 return 1;
1252 } 1252 }
1253 switch(op->type) { 1253 switch(op->type) {
1254 1254
1255 case SPELL_EFFECT: 1255 case SPELL_EFFECT:
1256 move_spell_effect(op); 1256 move_spell_effect(op);
1257 return 1; 1257 return 1;
1258 1258
1259 case ROD: 1259 case ROD:
1260 case HORN: 1260 case HORN:
1261 regenerate_rod(op); 1261 regenerate_rod(op);
1262 return 1; 1262 return 1;
1263 1263
1264 case FORCE: 1264 case FORCE:
1265 case POTION_EFFECT: 1265 case POTION_EFFECT:
1266 remove_force(op); 1266 remove_force(op);
1267 return 1; 1267 return 1;
1268 1268
1269 case BLINDNESS: 1269 case BLINDNESS:
1270 remove_blindness(op); 1270 remove_blindness(op);
1271 return 0; 1271 return 0;
1272 1272
1273 case POISONING: 1273 case POISONING:
1274 poison_more(op); 1274 poison_more(op);
1275 return 0; 1275 return 0;
1276 1276
1277 case DISEASE: 1277 case DISEASE:
1278 move_disease(op); 1278 move_disease(op);
1279 return 0; 1279 return 0;
1280 1280
1281 case SYMPTOM: 1281 case SYMPTOM:
1282 move_symptom(op); 1282 move_symptom(op);
1283 return 0; 1283 return 0;
1284 1284
1285 case THROWN_OBJ: 1285 case THROWN_OBJ:
1286 case ARROW: 1286 case ARROW:
1287 move_arrow(op); 1287 move_arrow(op);
1288 return 0; 1288 return 0;
1289 1289
1290 case LIGHTNING: /* It now moves twice as fast */ 1290 case LIGHTNING: /* It now moves twice as fast */
1291 move_bolt(op); 1291 move_bolt(op);
1292 return 0; 1292 return 0;
1293 1293
1294 case DOOR: 1294 case DOOR:
1295 remove_door(op); 1295 remove_door(op);
1296 return 0; 1296 return 0;
1297 1297
1298 case LOCKED_DOOR: 1298 case LOCKED_DOOR:
1299 remove_door2(op); 1299 remove_door2(op);
1300 return 0; 1300 return 0;
1301 1301
1302 case TELEPORTER: 1302 case TELEPORTER:
1303 move_teleporter(op); 1303 move_teleporter(op);
1304 return 0; 1304 return 0;
1305 1305
1306 case GOLEM: 1306 case GOLEM:
1307 move_golem(op); 1307 move_golem(op);
1308 return 0; 1308 return 0;
1309 1309
1310 case EARTHWALL: 1310 case EARTHWALL:
1311 hit_player(op, 2, op, AT_PHYSICAL, 1); 1311 hit_player(op, 2, op, AT_PHYSICAL, 1);
1312 return 0; 1312 return 0;
1313 1313
1314 case FIREWALL: 1314 case FIREWALL:
1315 move_firewall(op); 1315 move_firewall(op);
1316 if (op->stats.maxsp) 1316 if (op->stats.maxsp)
1317 animate_turning(op); 1317 animate_turning(op);
1318 return 0; 1318 return 0;
1319 1319
1320 case MOOD_FLOOR: 1320 case MOOD_FLOOR:
1321 do_mood_floor(op, op); 1321 do_mood_floor(op, op);
1322 return 0; 1322 return 0;
1323 1323
1324 case GATE: 1324 case GATE:
1325 move_gate(op); 1325 move_gate(op);
1326 return 0; 1326 return 0;
1327 1327
1328 case TIMED_GATE: 1328 case TIMED_GATE:
1329 move_timed_gate(op); 1329 move_timed_gate(op);
1330 return 0; 1330 return 0;
1331 1331
1332 case TRIGGER: 1332 case TRIGGER:
1333 case TRIGGER_BUTTON: 1333 case TRIGGER_BUTTON:
1334 case TRIGGER_PEDESTAL: 1334 case TRIGGER_PEDESTAL:
1335 case TRIGGER_ALTAR: 1335 case TRIGGER_ALTAR:
1336 animate_trigger(op); 1336 animate_trigger(op);
1337 return 0; 1337 return 0;
1338 1338
1339 case DETECTOR: 1339 case DETECTOR:
1340 move_detector(op); 1340 move_detector(op);
1341 1341
1342 case DIRECTOR: 1342 case DIRECTOR:
1343 if (op->stats.maxsp) 1343 if (op->stats.maxsp)
1344 animate_turning(op); 1344 animate_turning(op);
1345 return 0; 1345 return 0;
1346 1346
1347 case HOLE: 1347 case HOLE:
1348 move_hole(op); 1348 move_hole(op);
1349 return 0; 1349 return 0;
1350 1350
1351 case DEEP_SWAMP: 1351 case DEEP_SWAMP:
1352 move_deep_swamp(op); 1352 move_deep_swamp(op);
1353 return 0; 1353 return 0;
1354 1354
1355 case RUNE: 1355 case RUNE:
1356 case TRAP: 1356 case TRAP:
1357 move_rune(op); 1357 move_rune(op);
1358 return 0; 1358 return 0;
1359 1359
1360 case PLAYERMOVER: 1360 case PLAYERMOVER:
1361 move_player_mover(op); 1361 move_player_mover(op);
1362 return 0; 1362 return 0;
1363 1363
1364 case CREATOR: 1364 case CREATOR:
1365 move_creator(op); 1365 move_creator(op);
1366 return 0; 1366 return 0;
1367 1367
1368 case MARKER: 1368 case MARKER:
1369 move_marker(op); 1369 move_marker(op);
1370 return 0; 1370 return 0;
1371 1371
1372 case PLAYER_CHANGER: 1372 case PLAYER_CHANGER:
1373 move_player_changer(op); 1373 move_player_changer(op);
1374 return 0; 1374 return 0;
1375 1375
1376 case PEACEMAKER: 1376 case PEACEMAKER:
1377 move_peacemaker(op); 1377 move_peacemaker(op);
1378 return 0; 1378 return 0;
1379 } 1379 }
1380 1380
1381 return 0; 1381 return 0;
1382} 1382}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines