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.68 by root, Wed Sep 12 11:10:11 2007 UTC vs.
Revision 1.86 by elmex, Tue Jan 13 12:07:42 2009 UTC

1/* 1/*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team 4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 * 7 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify 8 * Deliantra is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or 10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version. 11 * (at your option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * 20 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de> 21 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 22 */
23 23
24/* 24/*
25 * Routines that is executed from objects based on their speed have been 25 * Routines that is executed from objects based on their speed have been
26 * collected in this file. 26 * collected in this file.
34 * so those will be removed shortly (in a cascade like fashion.) 34 * so those will be removed shortly (in a cascade like fashion.)
35 */ 35 */
36void 36void
37remove_door (object *op) 37remove_door (object *op)
38{ 38{
39 for (int i = 1; i < SIZEOFFREE1 + 1; i += 2)
40 {
41 object *tmp;
42 mapxy pos (op);
43 pos.move (i);
44 if (pos.normalise ()
45 && (tmp = present (DOOR, pos.m, pos.x, pos.y)))
46 {
47 tmp->set_speed (0.1f);
48 tmp->speed_left = -0.2f;
49 }
50 }
51
52 if (op->other_arch)
53 {
54 object *tmp = arch_to_object (op->other_arch);
55 tmp->x = op->x;
56 tmp->y = op->y;
57 tmp->map = op->map;
58 tmp->level = op->level;
59 insert_ob_in_map (tmp, op->map, op, 0);
60 }
61
62 op->drop_and_destroy ();
63}
64
65void
66remove_door2 (object *op)
67{
39 int i; 68 int i;
40 object *tmp; 69 object *tmp;
41 70
42 for (i = 1; i < 9; i += 2) 71 for (i = 1; i < 9; i += 2)
72 {
43 if ((tmp = present (DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i])) != NULL) 73 tmp = present (LOCKED_DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i]);
44 { 74 if (tmp && tmp->slaying == op->slaying)
75 { /* same key both doors */
45 tmp->set_speed (0.1f); 76 tmp->set_speed (0.1f);
46 tmp->speed_left = -0.2f; 77 tmp->speed_left = -0.2f;
47 } 78 }
79 }
48 80
49 if (op->other_arch) 81 if (op->other_arch)
50 { 82 {
51 tmp = arch_to_object (op->other_arch); 83 tmp = arch_to_object (op->other_arch);
52 tmp->x = op->x; 84 tmp->x = op->x;
54 tmp->map = op->map; 86 tmp->map = op->map;
55 tmp->level = op->level; 87 tmp->level = op->level;
56 insert_ob_in_map (tmp, op->map, op, 0); 88 insert_ob_in_map (tmp, op->map, op, 0);
57 } 89 }
58 90
59 op->destroy (); 91 op->drop_and_destroy ();
60}
61
62void
63remove_door2 (object *op)
64{
65 int i;
66 object *tmp;
67
68 for (i = 1; i < 9; i += 2)
69 {
70 tmp = present (LOCKED_DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i]);
71 if (tmp && tmp->slaying == op->slaying)
72 { /* same key both doors */
73 tmp->set_speed (0.1f);
74 tmp->speed_left = -0.2f;
75 }
76 }
77
78 if (op->other_arch)
79 {
80 tmp = arch_to_object (op->other_arch);
81 tmp->x = op->x;
82 tmp->y = op->y;
83 tmp->map = op->map;
84 tmp->level = op->level;
85 insert_ob_in_map (tmp, op->map, op, 0);
86 }
87
88 op->destroy ();
89} 92}
90 93
91void 94void
92generate_monster (object *gen) 95generate_monster (object *gen)
93{ 96{
94 if (!gen->map) 97 if (!gen->map)
95 return; 98 return;
96 99
97 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1)) 100 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1))
101 return;
102
103 // sleeping generators won't generate, this will make monsters like
104 // centipedes not generate more centipedes when being asleep.
105 if (gen->flag [FLAG_SLEEP])
98 return; 106 return;
99 107
100 object *op; 108 object *op;
101 int dir; 109 int dir;
102 110
114 122
115 dir = find_free_spot (op, gen->map, gen->x, gen->y, 1, SIZEOFFREE1 + 1); 123 dir = find_free_spot (op, gen->map, gen->x, gen->y, 1, SIZEOFFREE1 + 1);
116 if (dir < 0) 124 if (dir < 0)
117 return; 125 return;
118 126
119 op = object_create_clone (op); 127 op = op->deep_clone ();
120 128
121 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE); 129 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE);
122 unflag_inv (op, FLAG_IS_A_TEMPLATE); 130 unflag_inv (op, FLAG_IS_A_TEMPLATE);
123 } 131 }
124 else if (gen->other_arch) 132 else if (gen->other_arch)
297 } 305 }
298 else 306 else
299 { /* The gate is still going up */ 307 { /* The gate is still going up */
300 op->stats.wc++; 308 op->stats.wc++;
301 309
302 if ((int) op->stats.wc >= (NUM_ANIMATIONS (op))) 310 if (op->stats.wc >= NUM_ANIMATIONS (op))
303 op->stats.wc = (signed char) NUM_ANIMATIONS (op) - 1; 311 op->stats.wc = NUM_ANIMATIONS (op) - 1;
304 312
305 /* If there is something on top of the gate, we try to roll it off. 313 /* If there is something on top of the gate, we try to roll it off.
306 * If a player/monster, we don't roll, we just hit them with damage 314 * If a player/monster, we don't roll, we just hit them with damage
307 */ 315 */
308 if ((int) op->stats.wc >= NUM_ANIMATIONS (op) / 2) 316 if (op->stats.wc >= NUM_ANIMATIONS (op) / 2)
309 { 317 {
310 /* Halfway or further, check blocks */ 318 /* Halfway or further, check blocks */
311 /* First, get the top object on the square. */ 319 /* First, get the top object on the square. */
312 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above) 320 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above)
313 ; 321 ;
327 * off the gate. 335 * off the gate.
328 */ 336 */
329 else if (!QUERY_FLAG (tmp, FLAG_ALIVE) && (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL))) 337 else if (!QUERY_FLAG (tmp, FLAG_ALIVE) && (!QUERY_FLAG (tmp, FLAG_NO_PICK) || QUERY_FLAG (tmp, FLAG_CAN_ROLL)))
330 { 338 {
331 /* If it has speed, it should move itself, otherwise: */ 339 /* If it has speed, it should move itself, otherwise: */
332 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, 9); 340 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, SIZEOFFREE1 + 1);
333 341
334 /* If there is a free spot, move the object someplace */ 342 /* If there is a free spot, move the object someplace */
335 if (i != -1) 343 if (i > 0)
336 { 344 {
345 mapxy pos (tmp);
346 pos.move (i);
347 if (pos.normalise ())
337 tmp->remove (); 348 tmp->move_to (pos);
338 tmp->x += freearr_x[i], tmp->y += freearr_y[i];
339 insert_ob_in_map (tmp, op->map, op, 0);
340 } 349 }
341 } 350 }
342 } 351 }
343 352
344 /* See if there is still anything blocking the gate */ 353 /* See if there is still anything blocking the gate */
433 if (op->stats.sp == 1) 442 if (op->stats.sp == 1)
434 { 443 {
435 if (detected && last == 0) 444 if (detected && last == 0)
436 { 445 {
437 op->value = 1; 446 op->value = 1;
438 push_button (op); 447 push_button (op, tmp);
439 } 448 }
440 449
441 if (!detected && last == 1) 450 if (!detected && last == 1)
442 { 451 {
443 op->value = 0; 452 op->value = 0;
444 push_button (op); 453 push_button (op, tmp);
445 } 454 }
446 } 455 }
447 else 456 else
448 { /* in this case, we unset buttons */ 457 { /* in this case, we unset buttons */
449 if (detected && last == 1) 458 if (detected && last == 1)
450 { 459 {
451 op->value = 0; 460 op->value = 0;
452 push_button (op); 461 push_button (op, tmp);
453 } 462 }
454 463
455 if (!detected && last == 0) 464 if (!detected && last == 0)
456 { 465 {
457 op->value = 1; 466 op->value = 1;
458 push_button (op); 467 push_button (op, tmp);
459 } 468 }
460 } 469 }
461} 470}
462 471
463void 472void
476} 485}
477 486
478void 487void
479move_hole (object *op) 488move_hole (object *op)
480{ /* 1 = opening, 0 = closing */ 489{ /* 1 = opening, 0 = closing */
481 object *next, *tmp;
482
483 if (op->value) 490 if (op->value)
484 { /* We're opening */ 491 { /* We're opening */
485 if (--op->stats.wc <= 0) 492 if (--op->stats.wc <= 0)
486 { /* Opened, let's stop */ 493 { /* Opened, let's stop */
487 op->stats.wc = 0; 494 op->stats.wc = 0;
488 op->set_speed (0); 495 op->set_speed (0);
489 496
490 /* Hard coding this makes sense for holes I suppose */ 497 /* Hard coding this makes sense for holes I suppose */
491 op->move_on = MOVE_WALK; 498 op->move_on = MOVE_WALK;
492 for (tmp = op->above; tmp != NULL; tmp = next) 499 for (object *next, *tmp = op->above; tmp; tmp = next)
493 { 500 {
494 next = tmp->above; 501 next = tmp->above;
495 move_apply (op, tmp, tmp); 502 move_apply (op, tmp, tmp);
496 } 503 }
497 } 504 }
539 { 546 {
540 object *payload = op->inv; 547 object *payload = op->inv;
541 548
542 if (payload == NULL) 549 if (payload == NULL)
543 return NULL; 550 return NULL;
551
544 payload->remove (); 552 payload->remove ();
545 op->destroy (); 553 op->destroy ();
546 return payload; 554 return payload;
547 } 555 }
548 556
628 if (INVOKE_OBJECT (STOP, op)) 636 if (INVOKE_OBJECT (STOP, op))
629 return; 637 return;
630 638
631 if (op->inv) 639 if (op->inv)
632 { 640 {
641 // replace this by straightforward drop to ground?
633 object *payload = op->inv; 642 object *payload = op->inv;
634 643
635 payload->remove ();
636 payload->owner = 0; 644 payload->owner = 0;
637 insert_ob_in_map (payload, op->map, payload, 0); 645 insert_ob_in_map (payload, op->map, payload, 0);
638 op->destroy (); 646 op->destroy ();
639 } 647 }
640 else 648 else
669 * is if the player throws a bomb - the bomb explodes on its own, 677 * is if the player throws a bomb - the bomb explodes on its own,
670 * but this object sticks around. We could handle the cleanup in the 678 * but this object sticks around. We could handle the cleanup in the
671 * bomb code, but there are potential other cases where that could happen, 679 * bomb code, but there are potential other cases where that could happen,
672 * and it is easy enough to clean it up here. 680 * and it is easy enough to clean it up here.
673 */ 681 */
674 if (op->inv == NULL) 682 if (!op->inv)
675 { 683 {
676 op->destroy (); 684 op->destroy ();
677 return; 685 return;
678 } 686 }
679 687
849 op->remove (); 857 op->remove ();
850 for (i = 0; i < op->stats.food; i++) 858 for (i = 0; i < op->stats.food; i++)
851 { 859 {
852 object *tmp = arch_to_object (op->other_arch); 860 object *tmp = arch_to_object (op->other_arch);
853 861
854 if (op->type == LAMP)
855 tmp->stats.food = op->stats.food - 1;
856
857 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */ 862 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */
863
858 if (env) 864 if (env)
859 {
860 tmp = env->insert (tmp); 865 env->insert (tmp);
861
862 /* If this object is the players inventory, we need to tell the
863 * client of the change. Insert_ob_in_map takes care of the
864 * updating the client, so we don't need to do that below.
865 */
866 if (object *pl = op->in_player ())
867 {
868 esrv_del_item (pl->contr, op->count);
869 esrv_send_item (pl, tmp);
870 }
871 }
872 else 866 else
873 { 867 {
874 j = find_first_free_spot (tmp, op->map, op->x, op->y); 868 j = find_first_free_spot (tmp, op->map, op->x, op->y);
875 if (j < 0) /* No free spot */ 869 if (j < 0) /* No free spot */
876 tmp->destroy (); 870 tmp->destroy ();
943 else 937 else
944 { 938 {
945 /* Random teleporter */ 939 /* Random teleporter */
946 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp))) 940 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp)))
947 return; 941 return;
942
948 teleport (head, TELEPORTER, tmp); 943 teleport (head, TELEPORTER, tmp);
949 } 944 }
950} 945}
951 946
952/* This object will teleport someone to a different map 947/* This object will teleport someone to a different map
1172 { 1167 {
1173 creator->stats.hp = -1; 1168 creator->stats.hp = -1;
1174 return; 1169 return;
1175 } 1170 }
1176 1171
1177 if (creator->inv != NULL) 1172 if (creator->inv)
1178 { 1173 {
1179 object *ob; 1174 object *ob;
1180 int i; 1175 int i;
1181 object *ob_to_copy; 1176 object *ob_to_copy;
1182 1177
1187 if (rndm (0, i) == 0) 1182 if (rndm (0, i) == 0)
1188 { 1183 {
1189 ob_to_copy = ob; 1184 ob_to_copy = ob;
1190 } 1185 }
1191 } 1186 }
1192 new_ob = object_create_clone (ob_to_copy); 1187 new_ob = ob_to_copy->deep_clone ();
1193 CLEAR_FLAG (new_ob, FLAG_IS_A_TEMPLATE); 1188 CLEAR_FLAG (new_ob, FLAG_IS_A_TEMPLATE);
1194 unflag_inv (new_ob, FLAG_IS_A_TEMPLATE); 1189 unflag_inv (new_ob, FLAG_IS_A_TEMPLATE);
1195 } 1190 }
1196 else 1191 else
1197 { 1192 {
1198 if (creator->other_arch == NULL) 1193 if (!creator->other_arch)
1199 { 1194 {
1200 LOG (llevError, "move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n", 1195 LOG (llevError, "move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n",
1201 &creator->name, &creator->map->path, creator->x, creator->y); 1196 &creator->name, &creator->map->path, creator->x, creator->y);
1202 return; 1197 return;
1203 } 1198 }
1220 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y); 1215 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y);
1221 if (QUERY_FLAG (new_ob, FLAG_FREED)) 1216 if (QUERY_FLAG (new_ob, FLAG_FREED))
1222 return; 1217 return;
1223 1218
1224 if (creator->slaying) 1219 if (creator->slaying)
1225 {
1226 new_ob->name = new_ob->title = creator->slaying; 1220 new_ob->name = new_ob->title = creator->slaying;
1227 }
1228} 1221}
1229 1222
1230/* move_marker --peterm@soda.csua.berkeley.edu 1223/* move_marker --peterm@soda.csua.berkeley.edu
1231 when moved, a marker will search for a player sitting above 1224 when moved, a marker will search for a player sitting above
1232 it, and insert an invisible, weightless force into him 1225 it, and insert an invisible, weightless force into him
1264 } 1257 }
1265 } 1258 }
1266 } 1259 }
1267} 1260}
1268 1261
1262// mapscript objects activate themselves (only) then their timer fires
1263// TODO: maybe they should simply trigger the link like any other object?
1264void
1265move_mapscript (object *op)
1266{
1267 op->set_speed (0);
1268 cfperl_mapscript_activate (op, true, op, 0);
1269}
1270
1271void move_lamp (object *op)
1272{
1273 // if the lamp/torch is off, we should disable it.
1274 if (!op->glow_radius)
1275 {
1276 op->set_speed (0);
1277 return;
1278 }
1279 else
1280 {
1281 // check whether the face might needs to be updated
1282 // (currently this is needed to have already switched on torches
1283 // on maps, as they just set the glow_radius in the archetype)
1284 if (op->other_arch
1285 && (
1286 op->flag [FLAG_ANIMATE]
1287 ? (op->animation_id != op->other_arch->animation_id)
1288 : (op->face != op->other_arch->face)
1289 ))
1290 get_animation_from_arch (op, op->other_arch);
1291 }
1292
1293 // lamps and torches auf maps don't use up their fuel
1294 if (op->is_on_map ())
1295 return;
1296
1297 if (op->stats.food > 0)
1298 {
1299 op->stats.food--;
1300 return;
1301 }
1302
1303 apply_lamp (op, false);
1304}
1305
1269void 1306void
1270process_object (object *op) 1307process_object (object *op)
1271{ 1308{
1272 if (expect_false (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE))) 1309 if (expect_false (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE)))
1273 return; 1310 return;
1306 { 1343 {
1307 if (QUERY_FLAG (op, FLAG_APPLIED)) 1344 if (QUERY_FLAG (op, FLAG_APPLIED))
1308 remove_force (op); 1345 remove_force (op);
1309 else 1346 else
1310 { 1347 {
1311 /* If necessary, delete the item from the players inventory */ 1348 op->remove (); // TODO: really necessary?
1312 if (object *pl = op->in_player ())
1313 esrv_del_item (pl->contr, op->count);
1314
1315 op->remove ();
1316 1349
1317 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE)) 1350 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE))
1318 make_sure_not_seen (op); 1351 make_sure_not_seen (op);
1319 1352
1320 op->destroy (); 1353 op->drop_and_destroy ();
1321 } 1354 }
1322 1355
1323 return; 1356 return;
1324 } 1357 }
1325 } 1358 }
1449 1482
1450 case PLAYER: 1483 case PLAYER:
1451 // players have their own speed-management, so undo the --speed_left 1484 // players have their own speed-management, so undo the --speed_left
1452 ++op->speed_left; 1485 ++op->speed_left;
1453 break; 1486 break;
1454 }
1455}
1456 1487
1488 case MAPSCRIPT:
1489 move_mapscript (op);
1490 break;
1491
1492 case LAMP:
1493 case TORCH:
1494 move_lamp (op);
1495 break;
1496 }
1497}
1498

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines