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.70 by root, Mon Oct 22 20:59:25 2007 UTC vs.
Revision 1.95 by root, Mon Oct 26 11:31:39 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 it under
9 * it under the terms of the GNU General Public License as published by 9 * the terms of the Affero GNU General Public License as published by the
10 * the Free Software Foundation, either version 3 of the License, or 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * (at your option) any later version. 11 * 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,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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 Affero GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
20 * 21 *
21 * The authors can be reached via e-mail to <crossfire@schmorp.de> 22 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 23 */
23 24
24/* 25/*
25 * Routines that is executed from objects based on their speed have been 26 * Routines that is executed from objects based on their speed have been
26 * collected in this file. 27 * collected in this file.
34 * so those will be removed shortly (in a cascade like fashion.) 35 * so those will be removed shortly (in a cascade like fashion.)
35 */ 36 */
36void 37void
37remove_door (object *op) 38remove_door (object *op)
38{ 39{
39 int i;
40 object *tmp;
41
42 for (i = 1; i < SIZEOFFREE1 + 1; i += 2) 40 for (int i = 1; i < SIZEOFFREE1 + 1; i += 2)
43 { 41 {
42 object *tmp;
44 mapxy pos (op); 43 mapxy pos (op);
45 pos.move (i); 44 pos.move (i);
46 if (pos.normalise () 45 if (pos.normalise ()
47 && present (DOOR, pos.m, pos.x, pos.y)) 46 && (tmp = present (DOOR, pos.m, pos.x, pos.y)))
47 {
48 tmp->set_speed (0.1f);
49 tmp->speed_left = -0.2f;
48 { 50 }
51 }
52
53 if (op->other_arch)
54 {
55 object *tmp = arch_to_object (op->other_arch);
56 tmp->x = op->x;
57 tmp->y = op->y;
58 tmp->map = op->map;
59 tmp->level = op->level;
60 insert_ob_in_map (tmp, op->map, op, 0);
61 }
62
63 op->drop_and_destroy ();
64}
65
66void
67remove_door2 (object *op)
68{
69 int i;
70 object *tmp;
71
72 for (i = 1; i < 9; i += 2)
73 {
74 tmp = present (LOCKED_DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i]);
75 if (tmp && tmp->slaying == op->slaying)
76 { /* same key both doors */
49 tmp->set_speed (0.1f); 77 tmp->set_speed (0.1f);
50 tmp->speed_left = -0.2f; 78 tmp->speed_left = -0.2f;
51 } 79 }
52 } 80 }
53 81
59 tmp->map = op->map; 87 tmp->map = op->map;
60 tmp->level = op->level; 88 tmp->level = op->level;
61 insert_ob_in_map (tmp, op->map, op, 0); 89 insert_ob_in_map (tmp, op->map, op, 0);
62 } 90 }
63 91
64 op->destroy (); 92 op->drop_and_destroy ();
65}
66
67void
68remove_door2 (object *op)
69{
70 int i;
71 object *tmp;
72
73 for (i = 1; i < 9; i += 2)
74 {
75 tmp = present (LOCKED_DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i]);
76 if (tmp && tmp->slaying == op->slaying)
77 { /* same key both doors */
78 tmp->set_speed (0.1f);
79 tmp->speed_left = -0.2f;
80 }
81 }
82
83 if (op->other_arch)
84 {
85 tmp = arch_to_object (op->other_arch);
86 tmp->x = op->x;
87 tmp->y = op->y;
88 tmp->map = op->map;
89 tmp->level = op->level;
90 insert_ob_in_map (tmp, op->map, op, 0);
91 }
92
93 op->destroy ();
94} 93}
95 94
96void 95void
97generate_monster (object *gen) 96generate_monster (object *gen)
98{ 97{
99 if (!gen->map) 98 if (!gen->map)
100 return; 99 return;
101 100
102 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1)) 101 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1))
102 return;
103
104 // sleeping generators won't generate, this will make monsters like
105 // centipedes not generate more centipedes when being asleep.
106 if (gen->flag [FLAG_SLEEP])
103 return; 107 return;
104 108
105 object *op; 109 object *op;
106 int dir; 110 int dir;
107 111
119 123
120 dir = find_free_spot (op, gen->map, gen->x, gen->y, 1, SIZEOFFREE1 + 1); 124 dir = find_free_spot (op, gen->map, gen->x, gen->y, 1, SIZEOFFREE1 + 1);
121 if (dir < 0) 125 if (dir < 0)
122 return; 126 return;
123 127
124 op = object_create_clone (op); 128 op = op->deep_clone ();
125 129
126 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE); 130 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE);
127 unflag_inv (op, FLAG_IS_A_TEMPLATE); 131 unflag_inv (op, FLAG_IS_A_TEMPLATE);
128 } 132 }
129 else if (gen->other_arch) 133 else if (gen->other_arch)
439 if (op->stats.sp == 1) 443 if (op->stats.sp == 1)
440 { 444 {
441 if (detected && last == 0) 445 if (detected && last == 0)
442 { 446 {
443 op->value = 1; 447 op->value = 1;
444 push_button (op); 448 push_button (op, tmp);
445 } 449 }
446 450
447 if (!detected && last == 1) 451 if (!detected && last == 1)
448 { 452 {
449 op->value = 0; 453 op->value = 0;
450 push_button (op); 454 push_button (op, tmp);
451 } 455 }
452 } 456 }
453 else 457 else
454 { /* in this case, we unset buttons */ 458 { /* in this case, we unset buttons */
455 if (detected && last == 1) 459 if (detected && last == 1)
456 { 460 {
457 op->value = 0; 461 op->value = 0;
458 push_button (op); 462 push_button (op, tmp);
459 } 463 }
460 464
461 if (!detected && last == 0) 465 if (!detected && last == 0)
462 { 466 {
463 op->value = 1; 467 op->value = 1;
464 push_button (op); 468 push_button (op, tmp);
465 } 469 }
466 } 470 }
467} 471}
468 472
469void 473void
482} 486}
483 487
484void 488void
485move_hole (object *op) 489move_hole (object *op)
486{ /* 1 = opening, 0 = closing */ 490{ /* 1 = opening, 0 = closing */
487 object *next, *tmp;
488
489 if (op->value) 491 if (op->value)
490 { /* We're opening */ 492 { /* We're opening */
491 if (--op->stats.wc <= 0) 493 if (--op->stats.wc <= 0)
492 { /* Opened, let's stop */ 494 { /* Opened, let's stop */
493 op->stats.wc = 0; 495 op->stats.wc = 0;
494 op->set_speed (0); 496 op->set_speed (0);
495 497
496 /* Hard coding this makes sense for holes I suppose */ 498 /* Hard coding this makes sense for holes I suppose */
497 op->move_on = MOVE_WALK; 499 op->move_on = MOVE_WALK;
498 for (tmp = op->above; tmp != NULL; tmp = next) 500 for (object *next, *tmp = op->above; tmp; tmp = next)
499 { 501 {
500 next = tmp->above; 502 next = tmp->above;
501 move_apply (op, tmp, tmp); 503 move_apply (op, tmp, tmp);
502 } 504 }
503 } 505 }
545 { 547 {
546 object *payload = op->inv; 548 object *payload = op->inv;
547 549
548 if (payload == NULL) 550 if (payload == NULL)
549 return NULL; 551 return NULL;
552
550 payload->remove (); 553 payload->remove ();
551 op->destroy (); 554 op->destroy ();
552 return payload; 555 return payload;
553 } 556 }
554 557
597 600
598 // restore original wc, dam, attacktype and slaying 601 // restore original wc, dam, attacktype and slaying
599 op->stats.wc = op->stats.sp; 602 op->stats.wc = op->stats.sp;
600 op->stats.dam = op->stats.hp; 603 op->stats.dam = op->stats.hp;
601 op->attacktype = op->stats.grace; 604 op->attacktype = op->stats.grace;
605 op->slaying = op->custom_name;
602 606
603 if (op->spellarg)
604 {
605 op->slaying = op->spellarg;
606 free (op->spellarg);
607 op->spellarg = 0;
608 }
609 else
610 op->slaying = 0;
611
612 /* Reset these to zero, so that object::can_merge will work properly */ 607 /* Reset these to defaults, so that object::can_merge will work properly */
613 op->spellarg = NULL; 608 op->custom_name = 0;
614 op->stats.sp = 0; 609 op->stats.sp = 0;
615 op->stats.hp = 0; 610 op->stats.hp = 0;
616 op->stats.grace = 0; 611 op->stats.grace = 0;
617 op->level = 0; 612 op->level = 0;
618 op->face = op->arch->face; 613 op->face = op->arch->face;
619 op->owner = NULL; /* So that stopped arrows will be saved */ 614 op->owner = 0;
615
620 update_object (op, UP_OBJ_CHANGE); 616 update_object (op, UP_OBJ_CHANGE);
617
621 return op; 618 return op;
622} 619}
623 620
624/* stop_arrow() - what to do when a non-living flying object 621/* stop_arrow() - what to do when a non-living flying object
625 * has to stop. Sept 96 - I added in thrown object code in 622 * has to stop. Sept 96 - I added in thrown object code in
634 if (INVOKE_OBJECT (STOP, op)) 631 if (INVOKE_OBJECT (STOP, op))
635 return; 632 return;
636 633
637 if (op->inv) 634 if (op->inv)
638 { 635 {
636 // replace this by straightforward drop to ground?
639 object *payload = op->inv; 637 object *payload = op->inv;
640 638
641 payload->remove ();
642 payload->owner = 0; 639 payload->owner = 0;
643 insert_ob_in_map (payload, op->map, payload, 0); 640 insert_ob_in_map (payload, op->map, payload, 0);
644 op->destroy (); 641 op->destroy ();
645 } 642 }
646 else 643 else
675 * is if the player throws a bomb - the bomb explodes on its own, 672 * is if the player throws a bomb - the bomb explodes on its own,
676 * but this object sticks around. We could handle the cleanup in the 673 * but this object sticks around. We could handle the cleanup in the
677 * bomb code, but there are potential other cases where that could happen, 674 * bomb code, but there are potential other cases where that could happen,
678 * and it is easy enough to clean it up here. 675 * and it is easy enough to clean it up here.
679 */ 676 */
680 if (op->inv == NULL) 677 if (!op->inv)
681 { 678 {
682 op->destroy (); 679 op->destroy ();
683 return; 680 return;
684 } 681 }
685 682
814 return; 811 return;
815 } 812 }
816 813
817 /* update object image for new facing */ 814 /* update object image for new facing */
818 /* many thrown objects *don't* have more than one face */ 815 /* many thrown objects *don't* have more than one face */
819 if (GET_ANIM_ID (op)) 816 if (op->has_anim ())
820 SET_ANIMATION (op, op->direction); 817 op->set_anim_frame (op->direction);
821 } /* object is reflected */ 818 } /* object is reflected */
822 } /* object ran into a wall */ 819 } /* object ran into a wall */
823 820
824 /* decrease the speed as it flies. 0.05 means a standard bow will shoot 821 /* decrease the speed as it flies. 0.05 means a standard bow will shoot
825 * about 17 squares. Tune as needed. 822 * about 17 squares. Tune as needed.
855 op->remove (); 852 op->remove ();
856 for (i = 0; i < op->stats.food; i++) 853 for (i = 0; i < op->stats.food; i++)
857 { 854 {
858 object *tmp = arch_to_object (op->other_arch); 855 object *tmp = arch_to_object (op->other_arch);
859 856
860 if (op->type == LAMP)
861 tmp->stats.food = op->stats.food - 1;
862
863 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */ 857 tmp->stats.hp = op->stats.hp; /* The only variable it keeps. */
858
864 if (env) 859 if (env)
865 {
866 tmp = env->insert (tmp); 860 env->insert (tmp);
867
868 /* If this object is the players inventory, we need to tell the
869 * client of the change. Insert_ob_in_map takes care of the
870 * updating the client, so we don't need to do that below.
871 */
872 if (object *pl = op->in_player ())
873 {
874 esrv_del_item (pl->contr, op->count);
875 esrv_send_item (pl, tmp);
876 }
877 }
878 else 861 else
879 { 862 {
880 j = find_first_free_spot (tmp, op->map, op->x, op->y); 863 j = find_first_free_spot (tmp, op->map, op->x, op->y);
881 if (j < 0) /* No free spot */ 864 if (j < 0) /* No free spot */
882 tmp->destroy (); 865 tmp->destroy ();
949 else 932 else
950 { 933 {
951 /* Random teleporter */ 934 /* Random teleporter */
952 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp))) 935 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (tmp)))
953 return; 936 return;
937
954 teleport (head, TELEPORTER, tmp); 938 teleport (head, TELEPORTER, tmp);
955 } 939 }
956} 940}
957 941
958/* This object will teleport someone to a different map 942/* This object will teleport someone to a different map
1178 { 1162 {
1179 creator->stats.hp = -1; 1163 creator->stats.hp = -1;
1180 return; 1164 return;
1181 } 1165 }
1182 1166
1183 if (creator->inv != NULL) 1167 if (creator->inv)
1184 { 1168 {
1185 object *ob; 1169 object *ob;
1186 int i; 1170 int i;
1187 object *ob_to_copy; 1171 object *ob_to_copy;
1188 1172
1193 if (rndm (0, i) == 0) 1177 if (rndm (0, i) == 0)
1194 { 1178 {
1195 ob_to_copy = ob; 1179 ob_to_copy = ob;
1196 } 1180 }
1197 } 1181 }
1198 new_ob = object_create_clone (ob_to_copy); 1182 new_ob = ob_to_copy->deep_clone ();
1199 CLEAR_FLAG (new_ob, FLAG_IS_A_TEMPLATE); 1183 CLEAR_FLAG (new_ob, FLAG_IS_A_TEMPLATE);
1200 unflag_inv (new_ob, FLAG_IS_A_TEMPLATE); 1184 unflag_inv (new_ob, FLAG_IS_A_TEMPLATE);
1201 } 1185 }
1202 else 1186 else
1203 { 1187 {
1204 if (creator->other_arch == NULL) 1188 if (!creator->other_arch)
1205 { 1189 {
1206 LOG (llevError, "move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n", 1190 LOG (llevError, "move_creator: Creator doesn't have other arch set: %s (%s, %d, %d)\n",
1207 &creator->name, &creator->map->path, creator->x, creator->y); 1191 &creator->name, &creator->map->path, creator->x, creator->y);
1208 return; 1192 return;
1209 } 1193 }
1226 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y); 1210 insert_ob_in_map_at (new_ob, creator->map, creator, 0, creator->x, creator->y);
1227 if (QUERY_FLAG (new_ob, FLAG_FREED)) 1211 if (QUERY_FLAG (new_ob, FLAG_FREED))
1228 return; 1212 return;
1229 1213
1230 if (creator->slaying) 1214 if (creator->slaying)
1231 {
1232 new_ob->name = new_ob->title = creator->slaying; 1215 new_ob->name = new_ob->title = creator->slaying;
1233 }
1234} 1216}
1235 1217
1236/* move_marker --peterm@soda.csua.berkeley.edu 1218/* move_marker --peterm@soda.csua.berkeley.edu
1237 when moved, a marker will search for a player sitting above 1219 when moved, a marker will search for a player sitting above
1238 it, and insert an invisible, weightless force into him 1220 it, and insert an invisible, weightless force into him
1248 { 1230 {
1249 /* remove an old force with a slaying field == op->name */ 1231 /* remove an old force with a slaying field == op->name */
1250 if (object *force = tmp->force_find (op->name)) 1232 if (object *force = tmp->force_find (op->name))
1251 force->destroy (); 1233 force->destroy ();
1252 1234
1253 if (!tmp->force_find (op->slaying)) 1235 if (op->slaying && !tmp->force_find (op->slaying))
1254 { 1236 {
1255 tmp->force_add (op->slaying, op->stats.food); 1237 tmp->force_add (op->slaying, op->stats.food);
1256 1238
1257 if (op->msg) 1239 if (op->msg)
1258 new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, tmp, op->msg); 1240 new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, tmp, op->msg);
1270 } 1252 }
1271 } 1253 }
1272 } 1254 }
1273} 1255}
1274 1256
1257// mapscript objects activate themselves (only) then their timer fires
1258// TODO: maybe they should simply trigger the link like any other object?
1259void
1260move_mapscript (object *op)
1261{
1262 op->set_speed (0);
1263 cfperl_mapscript_activate (op, true, op, 0);
1264}
1265
1266void move_lamp (object *op)
1267{
1268 // if the lamp/torch is off, we should disable it.
1269 if (!op->glow_radius)
1270 {
1271 op->set_speed (0);
1272 return;
1273 }
1274 else
1275 {
1276 // check whether the face might need to be updated
1277 // (currently this is needed to have already switched on torches
1278 // on maps, as they just set the glow_radius in the archetype)
1279 if (op->other_arch
1280 && (
1281 (op->flag [FLAG_ANIMATE] != op->other_arch->flag [FLAG_ANIMATE])
1282 || (op->flag [FLAG_ANIMATE]
1283 ? (op->animation_id != op->other_arch->animation_id)
1284 : (op->face != op->other_arch->face))
1285 ))
1286 get_animation_from_arch (op, op->other_arch);
1287 }
1288
1289 // lamps and torches on maps don't use up their fuel
1290 if (op->is_on_map ())
1291 return;
1292
1293 if (op->stats.food > 0)
1294 {
1295 op->stats.food--;
1296 return;
1297 }
1298
1299 apply_lamp (op, false);
1300}
1301
1275void 1302void
1276process_object (object *op) 1303process_object (object *op)
1277{ 1304{
1278 if (expect_false (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE))) 1305 if (expect_false (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE)))
1279 return; 1306 return;
1312 { 1339 {
1313 if (QUERY_FLAG (op, FLAG_APPLIED)) 1340 if (QUERY_FLAG (op, FLAG_APPLIED))
1314 remove_force (op); 1341 remove_force (op);
1315 else 1342 else
1316 { 1343 {
1317 /* If necessary, delete the item from the players inventory */ 1344 op->remove (); // TODO: really necessary?
1318 if (object *pl = op->in_player ())
1319 esrv_del_item (pl->contr, op->count);
1320
1321 op->remove ();
1322 1345
1323 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE)) 1346 if (QUERY_FLAG (op, FLAG_SEE_ANYWHERE))
1324 make_sure_not_seen (op); 1347 make_sure_not_seen (op);
1325 1348
1326 op->destroy (); 1349 op->drop_and_destroy ();
1327 } 1350 }
1328 1351
1329 return; 1352 return;
1330 } 1353 }
1331 } 1354 }
1455 1478
1456 case PLAYER: 1479 case PLAYER:
1457 // players have their own speed-management, so undo the --speed_left 1480 // players have their own speed-management, so undo the --speed_left
1458 ++op->speed_left; 1481 ++op->speed_left;
1459 break; 1482 break;
1460 }
1461}
1462 1483
1484 case MAPSCRIPT:
1485 move_mapscript (op);
1486 break;
1487
1488 case LAMP:
1489 case TORCH:
1490 move_lamp (op);
1491 break;
1492 }
1493}
1494

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines