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.32 by elmex, Wed Jan 3 00:56:40 2007 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);
272} 220}
273 221
274 222
275void 223void
276move_gate (object *op) 224move_gate (object *op)
277{ /* 1 = going down, 0 = goind up */ 225{ /* 1 = going down, 0 = going up */
278 object *tmp; 226 object *tmp;
279 227
280 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))
281 { 229 {
282 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));
354 */ 302 */
355 if ((int) op->stats.wc >= NUM_ANIMATIONS (op) / 2) 303 if ((int) op->stats.wc >= NUM_ANIMATIONS (op) / 2)
356 { 304 {
357 /* Halfway or further, check blocks */ 305 /* Halfway or further, check blocks */
358 /* First, get the top object on the square. */ 306 /* First, get the top object on the square. */
359 for (tmp = op->above; tmp != NULL && tmp->above != NULL; tmp = tmp->above); 307 for (tmp = op->above; tmp && tmp->above; tmp = tmp->above)
308 ;
360 309
361 if (tmp != NULL) 310 if (tmp)
362 { 311 {
363 if (QUERY_FLAG (tmp, FLAG_ALIVE)) 312 if (QUERY_FLAG (tmp, FLAG_ALIVE))
364 { 313 {
365 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
366 if (tmp->type == PLAYER) 316 if (tmp->type == PLAYER)
367 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);
368 } 318 }
369 else 319 else
370 /* If the object is not alive, and the object either can 320 /* If the object is not alive, and the object either can
456 406
457 if (op->stats.hp) 407 if (op->stats.hp)
458 { 408 {
459 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below) 409 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp2->below)
460 { 410 {
461 if (op->slaying && !strcmp (op->slaying, tmp->name)) 411 if (op->slaying && op->slaying == tmp->name)
462 detected = 1; 412 detected = 1;
413
463 if (tmp2->type == FORCE && tmp2->slaying && !strcmp (tmp2->slaying, op->slaying)) 414 if (tmp2->type == FORCE && tmp2->slaying && tmp2->slaying == op->slaying)
464 detected = 1; 415 detected = 1;
465 } 416 }
466 } 417 }
418
467 if (op->slaying && !strcmp (op->slaying, tmp->name)) 419 if (op->slaying && op->slaying == tmp->name)
468 {
469 detected = 1; 420 detected = 1;
470 }
471 else if (tmp->type == SPECIAL_KEY && tmp->slaying == op->slaying) 421 else if (tmp->type == SPECIAL_KEY && tmp->slaying == op->slaying)
472 detected = 1; 422 detected = 1;
473 } 423 }
474 424
475 /* the detector sets the button if detection is found */ 425 /* the detector sets the button if detection is found */
605void 555void
606fix_stopped_item (object *op, maptile *map, object *originator) 556fix_stopped_item (object *op, maptile *map, object *originator)
607{ 557{
608 if (map == NULL) 558 if (map == NULL)
609 return; 559 return;
560
610 if (QUERY_FLAG (op, FLAG_REMOVED)) 561 if (QUERY_FLAG (op, FLAG_REMOVED))
611 insert_ob_in_map (op, map, originator, 0); 562 insert_ob_in_map (op, map, originator, 0);
612 else if (op->type == ARROW) 563 else if (op->type == ARROW)
613 merge_ob (op, NULL); /* only some arrows actually need this */ 564 merge_ob (op, NULL); /* only some arrows actually need this */
614} 565}
615
616 566
617object * 567object *
618fix_stopped_arrow (object *op) 568fix_stopped_arrow (object *op)
619{ 569{
620 if (rndm (0, 99) < op->stats.food) 570 if (rndm (0, 99) < op->stats.food)
649 op->stats.hp = 0; 599 op->stats.hp = 0;
650 op->stats.grace = 0; 600 op->stats.grace = 0;
651 op->level = 0; 601 op->level = 0;
652 op->face = op->arch->clone.face; 602 op->face = op->arch->clone.face;
653 op->owner = NULL; /* So that stopped arrows will be saved */ 603 op->owner = NULL; /* So that stopped arrows will be saved */
654 update_object (op, UP_OBJ_FACE); 604 update_object (op, UP_OBJ_CHANGE);
655 return op; 605 return op;
656} 606}
657 607
658/* stop_arrow() - what to do when a non-living flying object 608/* stop_arrow() - what to do when a non-living flying object
659 * 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
685 } 635 }
686} 636}
687 637
688/* 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.
689 */ 639 */
690
691void 640void
692move_arrow (object *op) 641move_arrow (object *op)
693{ 642{
694 object *tmp; 643 object *tmp;
695 sint16 new_x, new_y; 644 sint16 new_x, new_y;
766 * as below. (Note that for living creatures there is a small 715 * as below. (Note that for living creatures there is a small
767 * chance that reflect_missile fails.) 716 * chance that reflect_missile fails.)
768 */ 717 */
769 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))
770 { 719 {
771 int number = op->face->number; 720 int number = op->face;
772 721
773 op->direction = absdir (op->direction + 4); 722 op->direction = absdir (op->direction + 4);
774 op->state = 0; 723 update_turn_face (op);
775
776 if (GET_ANIM_ID (op))
777 {
778 number += 4;
779
780 if (number > GET_ANIMATION (op, 8))
781 number -= 8;
782
783 op->face = &new_faces[number];
784 }
785
786 was_reflected = 1; /* skip normal movement calculations */ 724 was_reflected = 1; /* skip normal movement calculations */
787 } 725 }
788 else 726 else
789 { 727 {
790 /* Attack the object. */ 728 /* Attack the object. */
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 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