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.28 by root, Sat Dec 30 10:16:11 2006 UTC vs.
Revision 1.46 by root, Sat Apr 28 21:34:38 2007 UTC

1/* 1/*
2 CrossFire, A Multiplayer game for X-windows 2 * CrossFire, A Multiplayer game
3 3 *
4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
5 Copyright (C) 1992 Frank Tore Johansen 6 * Copyright (C) 1992 Frank Tore Johansen
6 7 *
7 This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 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
9 the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version. 11 * (at your option) any later version.
11 12 *
12 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,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details. 16 * GNU General Public License for more details.
16 17 *
17 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
18 along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 21 *
21 The authors can be reached via e-mail at <crossfire@schmorp.de> 22 * The authors can be reached via e-mail at <crossfire@schmorp.de>
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.
27 */ 28 */
28
29#include <global.h> 29#include <global.h>
30#include <spells.h> 30#include <spells.h>
31#include <sproto.h> 31#include <sproto.h>
32 32
33/* The following removes doors. The functions check to see if similar 33/* The following removes doors. The functions check to see if similar
34 * doors are next to the one that is being removed, and if so, set it 34 * doors are next to the one that is being removed, and if so, set it
35 * so those will be removed shortly (in a cascade like fashion.) 35 * so those will be removed shortly (in a cascade like fashion.)
36 */ 36 */
37
38void 37void
39remove_door (object *op) 38remove_door (object *op)
40{ 39{
41 int i; 40 int i;
42 object *tmp; 41 object *tmp;
88 } 87 }
89 88
90 op->destroy (); 89 op->destroy ();
91} 90}
92 91
93/* Will generate a monster according to content
94 * of generator.
95 */
96void 92void
97generate_monster_inv (object *gen) 93generate_monster (object *gen)
98{ 94{
99 int i;
100 object *op, *head = NULL;
101
102 int qty = 0;
103
104 /* Code below assumes the generator is on a map, as it tries
105 * to place the monster on the map. So if the generator
106 * isn't on a map, complain and exit.
107 */
108 if (gen->map == NULL)
109 {
110 //LOG(llevError,"Generator (%s) not on a map?\n", gen->name);
111 return;
112 }
113 /*First count numer of objects in inv */
114 for (op = gen->inv; op; op = op->below)
115 qty++;
116 if (!qty)
117 {
118 LOG (llevError, "Generator (%s) has no inventory in generate_monster_inv?\n", &gen->name);
119 return; /*No inventory */
120 }
121 qty = rndm (0, qty - 1);
122 for (op = gen->inv; qty; qty--)
123 op = op->below;
124 i = find_free_spot (op, gen->map, gen->x, gen->y, 1, 9);
125 if (i == -1)
126 return;
127 head = object_create_clone (op);
128 CLEAR_FLAG (head, FLAG_IS_A_TEMPLATE);
129 unflag_inv (head, FLAG_IS_A_TEMPLATE);
130 if (rndm (0, 9))
131 generate_artifact (head, gen->map->difficulty);
132 insert_ob_in_map_at (head, gen->map, gen, 0, gen->x + freearr_x[i], gen->y + freearr_y[i]);
133 if (QUERY_FLAG (head, FLAG_FREED))
134 return;
135 if (head->has_random_items ())
136 create_treasure (head->randomitems, head, GT_APPLY, gen->map->difficulty, 0);
137}
138
139void
140generate_monster_arch (object *gen)
141{
142 int i;
143 object *op, *head = NULL, *prev = NULL;
144 archetype *at = gen->other_arch;
145
146 if (!gen->other_arch)
147 return;
148
149 /* Code below assumes the generator is on a map, as it tries
150 * to place the monster on the map. So if the generator
151 * isn't on a map, complain and exit.
152 */
153 if (!gen->map) 95 if (!gen->map)
154 return; 96 return;
155 97
156 i = find_free_spot (&at->clone, gen->map, gen->x, gen->y, 1, 9);
157 if (i == -1)
158 return;
159
160 while (at)
161 {
162 op = arch_to_object (at);
163 op->x = gen->x + freearr_x[i] + at->clone.x;
164 op->y = gen->y + freearr_y[i] + at->clone.y;
165
166 if (head)
167 op->head = head, prev->more = op;
168
169 if (rndm (0, 9))
170 generate_artifact (op, gen->map->difficulty);
171
172 insert_ob_in_map (op, gen->map, gen, 0);
173 if (QUERY_FLAG (op, FLAG_FREED))
174 return;
175
176 if (op->has_random_items ())
177 create_treasure (op->randomitems, op, GT_APPLY, gen->map->difficulty, 0);
178
179 if (head == NULL)
180 head = op;
181
182 prev = op;
183 at = at->more;
184 }
185}
186
187void
188generate_monster (object *gen)
189{
190
191 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1)) 98 if (GENERATE_SPEED (gen) && rndm (0, GENERATE_SPEED (gen) - 1))
192 return; 99 return;
193 100
101 object *op;
102
194 if (QUERY_FLAG (gen, FLAG_CONTENT_ON_GEN)) 103 if (QUERY_FLAG (gen, FLAG_CONTENT_ON_GEN))
195 generate_monster_inv (gen); 104 {
105 // either copy one item form the inventory...
106 if (!gen->inv)
107 return;
108
109 // first select one item from the inventory
110 int index = 0;
111 for (object *tmp = gen->inv; tmp; tmp = tmp->below)
112 if (!rndm (++index))
113 op = tmp;
114
115 op = object_create_clone (op);
116
117 CLEAR_FLAG (op, FLAG_IS_A_TEMPLATE);
118 unflag_inv (op, FLAG_IS_A_TEMPLATE);
119 }
196 else 120 else
197 generate_monster_arch (gen); 121 {
122 // ...or use other_arch
123 if (archetype *at = gen->other_arch)
124 op = arch_to_object (at);
125 else
126 return;
127 }
198 128
129 op->expand_tail ();
130
131 int i = find_free_spot (op, gen->map, gen->x, gen->y, 1, 9);
132 if (i >= 0)
133 {
134 if (insert_ob_in_map_at (op, gen->map, gen, 0, gen->x + freearr_x[i], gen->y + freearr_y[i]))
135 {
136 if (rndm (0, 9))
137 generate_artifact (op, gen->map->difficulty);
138
139 if (op->has_random_items ())
140 create_treasure (op->randomitems, op, GT_APPLY, gen->map->difficulty);
141
142 return;
143 }
144 }
145
146 op->destroy ();
199} 147}
200 148
201void 149void
202remove_force (object *op) 150remove_force (object *op)
203{ 151{
246 return; 194 return;
247 } 195 }
248 196
249 if (op->stats.food == 1) 197 if (op->stats.food == 1)
250 { 198 {
251 /* need to remove the object before fix_player is called, else fix_player 199 /* need to unapply the object before update_stats is called, else fix_player
252 * will not do anything. 200 * will not do anything.
253 */ 201 */
254 if (op->env->type == PLAYER) 202 if (op->env->type == PLAYER)
255 { 203 {
256 CLEAR_FLAG (op, FLAG_APPLIED); 204 CLEAR_FLAG (op, FLAG_APPLIED);
265 if (op->env->type == PLAYER) 213 if (op->env->type == PLAYER)
266 { 214 {
267 op->env->stats.food--; 215 op->env->stats.food--;
268 new_draw_info (NDI_UNIQUE, 0, op->env, "You feel very sick..."); 216 new_draw_info (NDI_UNIQUE, 0, op->env, "You feel very sick...");
269 } 217 }
218
270 (void) hit_player (op->env, op->stats.dam, op, AT_INTERNAL, 1); 219 hit_player (op->env, op->stats.dam, op, AT_INTERNAL, 1);
271} 220}
272 221
273 222
274void 223void
275move_gate (object *op) 224move_gate (object *op)
276{ /* 1 = going down, 0 = goind up */ 225{ /* 1 = going down, 0 = going up */
277 object *tmp; 226 object *tmp;
278 227
279 if (op->stats.wc < 0 || (int) op->stats.wc >= NUM_ANIMATIONS (op)) 228 if (op->stats.wc < 0 || (int) op->stats.wc >= NUM_ANIMATIONS (op))
280 { 229 {
281 LOG (llevError, "Gate error: animation was %d, max=%d\n", op->stats.wc, NUM_ANIMATIONS (op)); 230 LOG (llevError, "Gate error: animation was %d, max=%d\n", op->stats.wc, NUM_ANIMATIONS (op));
353 */ 302 */
354 if ((int) op->stats.wc >= NUM_ANIMATIONS (op) / 2) 303 if ((int) op->stats.wc >= NUM_ANIMATIONS (op) / 2)
355 { 304 {
356 /* Halfway or further, check blocks */ 305 /* Halfway or further, check blocks */
357 /* First, get the top object on the square. */ 306 /* First, get the top object on the square. */
358 for (tmp = op->above; tmp != NULL && tmp->above != NULL; tmp = tmp->above); 307 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above)
308 ;
359 309
360 if (tmp != NULL) 310 if (tmp)
361 { 311 {
362 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 312 if (QUERY_FLAG (tmp, FLAG_ALIVE))
363 { 313 {
364 hit_player (tmp, random_roll (1, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1); 314 hit_player (tmp, random_roll (0, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1);
315
365 if (tmp->type == PLAYER) 316 if (tmp->type == PLAYER)
366 new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are crushed by the %s!", &op->name); 317 new_draw_info_format (NDI_UNIQUE, 0, tmp, "You are crushed by the %s!", &op->name);
367 } 318 }
368 else 319 else
369 /* If the object is not alive, and the object either can 320 /* If the object is not alive, and the object either can
455 406
456 if (op->stats.hp) 407 if (op->stats.hp)
457 { 408 {
458 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below) 409 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
459 { 410 {
460 if (op->slaying && !strcmp (op->slaying, tmp->name)) 411 if (op->slaying && op->slaying == tmp->name)
461 detected = 1; 412 detected = 1;
413
462 if (tmp2->type == FORCE && tmp2->slaying && !strcmp (tmp2->slaying, op->slaying)) 414 if (tmp2->type == FORCE && tmp2->slaying && tmp2->slaying == op->slaying)
463 detected = 1; 415 detected = 1;
464 } 416 }
465 } 417 }
418
466 if (op->slaying && !strcmp (op->slaying, tmp->name)) 419 if (op->slaying && op->slaying == tmp->name)
467 {
468 detected = 1; 420 detected = 1;
469 }
470 else if (tmp->type == SPECIAL_KEY && tmp->slaying == op->slaying) 421 else if (tmp->type == SPECIAL_KEY && tmp->slaying == op->slaying)
471 detected = 1; 422 detected = 1;
472 } 423 }
473 424
474 /* the detector sets the button if detection is found */ 425 /* the detector sets the button if detection is found */
585 op->destroy (); 536 op->destroy ();
586 return payload; 537 return payload;
587 } 538 }
588 539
589 case ARROW: 540 case ARROW:
590 if (op->speed >= MIN_ACTIVE_SPEED) 541 if (op->has_active_speed ())
591 op = fix_stopped_arrow (op); 542 op = fix_stopped_arrow (op);
592 return op; 543 return op;
593 544
594 default: 545 default:
595 return op; 546 return op;
604void 555void
605fix_stopped_item (object *op, maptile *map, object *originator) 556fix_stopped_item (object *op, maptile *map, object *originator)
606{ 557{
607 if (map == NULL) 558 if (map == NULL)
608 return; 559 return;
560
609 if (QUERY_FLAG (op, FLAG_REMOVED)) 561 if (QUERY_FLAG (op, FLAG_REMOVED))
610 insert_ob_in_map (op, map, originator, 0); 562 insert_ob_in_map (op, map, originator, 0);
611 else if (op->type == ARROW) 563 else if (op->type == ARROW)
612 merge_ob (op, NULL); /* only some arrows actually need this */ 564 merge_ob (op, NULL); /* only some arrows actually need this */
613} 565}
614
615 566
616object * 567object *
617fix_stopped_arrow (object *op) 568fix_stopped_arrow (object *op)
618{ 569{
619 if (rndm (0, 99) < op->stats.food) 570 if (rndm (0, 99) < op->stats.food)
648 op->stats.hp = 0; 599 op->stats.hp = 0;
649 op->stats.grace = 0; 600 op->stats.grace = 0;
650 op->level = 0; 601 op->level = 0;
651 op->face = op->arch->clone.face; 602 op->face = op->arch->clone.face;
652 op->owner = NULL; /* So that stopped arrows will be saved */ 603 op->owner = NULL; /* So that stopped arrows will be saved */
653 update_object (op, UP_OBJ_FACE); 604 update_object (op, UP_OBJ_CHANGE);
654 return op; 605 return op;
655} 606}
656 607
657/* stop_arrow() - what to do when a non-living flying object 608/* stop_arrow() - what to do when a non-living flying object
658 * has to stop. Sept 96 - I added in thrown object code in 609 * has to stop. Sept 96 - I added in thrown object code in
684 } 635 }
685} 636}
686 637
687/* Move an arrow along its course. op is the arrow or thrown object. 638/* Move an arrow along its course. op is the arrow or thrown object.
688 */ 639 */
689
690void 640void
691move_arrow (object *op) 641move_arrow (object *op)
692{ 642{
693 object *tmp; 643 object *tmp;
694 sint16 new_x, new_y; 644 sint16 new_x, new_y;
765 * as below. (Note that for living creatures there is a small 715 * as below. (Note that for living creatures there is a small
766 * chance that reflect_missile fails.) 716 * chance that reflect_missile fails.)
767 */ 717 */
768 if (QUERY_FLAG (tmp, FLAG_REFL_MISSILE) && (rndm (0, 99)) < (90 - op->level / 10)) 718 if (QUERY_FLAG (tmp, FLAG_REFL_MISSILE) && (rndm (0, 99)) < (90 - op->level / 10))
769 { 719 {
770 int number = op->face->number; 720 int number = op->face;
771 721
772 op->direction = absdir (op->direction + 4); 722 op->direction = absdir (op->direction + 4);
773 op->state = 0; 723 update_turn_face (op);
774
775 if (GET_ANIM_ID (op))
776 {
777 number += 4;
778
779 if (number > GET_ANIMATION (op, 8))
780 number -= 8;
781
782 op->face = &new_faces[number];
783 }
784
785 was_reflected = 1; /* skip normal movement calculations */ 724 was_reflected = 1; /* skip normal movement calculations */
786 } 725 }
787 else 726 else
788 { 727 {
789 /* Attack the object. */ 728 /* Attack the object. */
963 * there is an old multipart teleporter in which the other parts 902 * there is an old multipart teleporter in which the other parts
964 * have speed, we don't really want to call it twice for the same 903 * have speed, we don't really want to call it twice for the same
965 * function - in fact, as written below, part N would get called 904 * function - in fact, as written below, part N would get called
966 * N times without the speed check. 905 * N times without the speed check.
967 */ 906 */
968 if (op->more && FABS (op->more->speed) < MIN_ACTIVE_SPEED) 907 if (op->more && !op->more->has_active_speed ())
969 move_teleporter (op->more); 908 move_teleporter (op->more);
970 909
971 if (op->head) 910 if (op->head)
972 head = op->head; 911 head = op->head;
973 912
1019/* This object will teleport someone to a different map 958/* This object will teleport someone to a different map
1020 and will also apply changes to the player from its inventory. 959 and will also apply changes to the player from its inventory.
1021 This was invented for giving classes, but there's no reason it 960 This was invented for giving classes, but there's no reason it
1022 can't be generalized. 961 can't be generalized.
1023*/ 962*/
1024
1025void 963void
1026move_player_changer (object *op) 964move_player_changer (object *op)
1027{ 965{
1028 object *player; 966 object *player;
1029 object *walk; 967 object *walk;
1030 char c;
1031 968
1032 if (!op->above || !EXIT_PATH (op)) 969 if (!op->above || !EXIT_PATH (op))
1033 return; 970 return;
1034 971
1035 /* This isn't all that great - means that the player_mover 972 /* This isn't all that great - means that the player_mover
1036 * needs to be on top. 973 * needs to be on top.
1037 */ 974 */
1038 if (op->above->type == PLAYER) 975 if (op->above->type == PLAYER)
1039 { 976 {
1040 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (player))) 977 if (INVOKE_OBJECT (TRIGGER, op, ARG_OBJECT (player)))
1041 return; 978 return;
979
1042 player = op->above; 980 player = op->above;
1043 981
1044 for (walk = op->inv; walk != NULL; walk = walk->below) 982 for (walk = op->inv; walk; walk = walk->below)
1045 apply_changes_to_player (player, walk); 983 apply_changes_to_player (player, walk);
1046 984
1047 player->update_stats (); 985 player->update_stats ();
1048 986
1049 esrv_send_inventory (op->above, op->above); 987 esrv_send_inventory (op->above, op->above);
1050 esrv_update_item (UPD_FACE, op->above, op->above); 988 esrv_update_item (UPD_FACE, op->above, op->above);
1051 989
1052 /* update players death & WoR home-position */ 990 /* update players death & WoR home-position */
1053 sscanf (EXIT_PATH (op), "%c", &c); 991 if (*EXIT_PATH (op) == '/')
1054 if (c == '/')
1055 { 992 {
1056 strcpy (player->contr->savebed_map, EXIT_PATH (op)); 993 player->contr->savebed_map = EXIT_PATH (op);
1057 player->contr->bed_x = EXIT_X (op); 994 player->contr->bed_x = EXIT_X (op);
1058 player->contr->bed_y = EXIT_Y (op); 995 player->contr->bed_y = EXIT_Y (op);
1059 } 996 }
1060 else 997 else
1061 LOG (llevDebug, "WARNING: destination '%s' in player_changer must be an absolute path!\n", &EXIT_PATH (op)); 998 LOG (llevDebug, "WARNING: destination '%s' in player_changer must be an absolute path!\n", &EXIT_PATH (op));
1062 999
1063 op->above->enter_exit (op); 1000 op->above->enter_exit (op);
1064 player->contr->save ();
1065 } 1001 }
1066} 1002}
1067 1003
1068/* firewalls fire other spells. 1004/* firewalls fire other spells.
1069 * The direction of the wall is stored in op->stats.sp. 1005 * The direction of the wall is stored in op->stats.sp.
1207 return; 1143 return;
1208 } 1144 }
1209 1145
1210 if (op->above == NULL) 1146 if (op->above == NULL)
1211 return; 1147 return;
1148
1212 for (tmp = op->above; tmp != NULL; tmp = tmp->above) 1149 for (tmp = op->above; tmp; tmp = tmp->above)
1213 { 1150 {
1214 if (strcmp (op->other_arch->name, tmp->arch->name) == 0) 1151 if (op->other_arch->name == tmp->arch->name)
1215 { 1152 {
1216 if (op->level <= 0) 1153 if (op->level <= 0)
1217 tmp->destroy (); 1154 tmp->destroy ();
1218 else 1155 else
1219 { 1156 {
1310 with a specific code as the slaying field. 1247 with a specific code as the slaying field.
1311 At that time, it writes the contents of its own message 1248 At that time, it writes the contents of its own message
1312 field to the player. The marker will decrement hp to 1249 field to the player. The marker will decrement hp to
1313 0 and then delete itself every time it grants a mark. 1250 0 and then delete itself every time it grants a mark.
1314 unless hp was zero to start with, in which case it is infinite.*/ 1251 unless hp was zero to start with, in which case it is infinite.*/
1315
1316void 1252void
1317move_marker (object *op) 1253move_marker (object *op)
1318{ 1254{
1319 if (object *tmp = op->ms ().player ()) 1255 if (object *tmp = op->ms ().player ())
1320 { 1256 {
1321 object *tmp2; 1257 object *tmp2;
1322 1258
1323 /* remove an old force with a slaying field == op->name */ 1259 /* remove an old force with a slaying field == op->name */
1324 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below) 1260 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1325 if (tmp2->type == FORCE && tmp2->slaying && !strcmp (tmp2->slaying, op->name)) 1261 if (tmp2->type == FORCE && tmp2->slaying && tmp2->slaying == op->name)
1326 { 1262 {
1327 tmp2->destroy (); 1263 tmp2->destroy ();
1328 break; 1264 break;
1329 } 1265 }
1330 1266
1331 /* cycle through his inventory to look for the MARK we want to 1267 /* cycle through his inventory to look for the MARK we want to
1332 * place 1268 * place
1333 */ 1269 */
1334 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below) 1270 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
1335 if (tmp2->type == FORCE && tmp2->slaying && !strcmp (tmp2->slaying, op->slaying)) 1271 if (tmp2->type == FORCE && tmp2->slaying && tmp2->slaying == op->slaying)
1336 break; 1272 break;
1337 1273
1338 /* if we didn't find our own MARK */ 1274 /* if we didn't find our own MARK */
1339 if (tmp2 == NULL) 1275 if (!tmp2)
1340 { 1276 {
1341 object *force = get_archetype (FORCE_NAME); 1277 object *force = get_archetype (FORCE_NAME);
1342 1278
1343 if (op->stats.food) 1279 if (op->stats.food)
1344 { 1280 {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines