|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 00042 int open_door(object *op, mapstruct *m, int x, int y, int mode) 00043 { 00044 object *tmp, *key = NULL; 00045 00046 /* Make sure a monster/NPC can actually open doors */ 00047 if (op->type == MONSTER && !(op->behavior & BEHAVIOR_OPEN_DOORS)) 00048 { 00049 return 0; 00050 } 00051 00052 /* Look for objects on layer 5. */ 00053 for (tmp = GET_MAP_OB_LAYER(m, x, y, LAYER_WALL - 1); tmp && tmp->layer == LAYER_WALL; tmp = tmp->above) 00054 { 00055 if (tmp->type == DOOR) 00056 { 00057 /* Door needs a key? */ 00058 if (tmp->slaying) 00059 { 00060 if (!(key = find_key(op, tmp))) 00061 { 00062 if (op->type == PLAYER && mode) 00063 { 00064 new_draw_info(0, COLOR_NAVY, op, tmp->msg); 00065 } 00066 00067 return 0; 00068 } 00069 } 00070 00071 /* If we are here, the door can be opened */ 00072 if (mode) 00073 { 00074 open_locked_door(tmp, op); 00075 00076 if (op->type == PLAYER && key) 00077 { 00078 if (key->type == KEY) 00079 { 00080 new_draw_info_format(0, COLOR_WHITE, op, "You open the door with the %s.", query_short_name(key, NULL)); 00081 } 00082 else if (key->type == FORCE) 00083 { 00084 new_draw_info(0, COLOR_WHITE, op, "The door is opened for you."); 00085 } 00086 } 00087 } 00088 00089 return 1; 00090 } 00091 } 00092 00093 LOG(llevSystem, "open_door() - Door on wrong layer. Map: %s (%d, %d) (op: %s)\n", m->path, x, y, query_name(op, NULL)); 00094 return 0; 00095 } 00096 00102 object *find_key(object *op, object *door) 00103 { 00104 object *tmp, *key; 00105 00106 /* First, let's try to find a key in the top level inventory. */ 00107 for (tmp = op->inv; tmp; tmp = tmp->below) 00108 { 00109 if ((tmp->type == KEY || tmp->type == FORCE) && tmp->slaying == door->slaying) 00110 { 00111 return tmp; 00112 } 00113 00114 /* Go through containers. */ 00115 if (tmp->type == CONTAINER && tmp->inv) 00116 { 00117 key = find_key(tmp, door); 00118 00119 if (key) 00120 { 00121 return key; 00122 } 00123 } 00124 } 00125 00126 return NULL; 00127 } 00128 00135 void open_locked_door(object *op, object *opener) 00136 { 00137 object *tmp, *tmp2; 00138 00139 /* If set, just exchange and delete old door */ 00140 if (op->other_arch) 00141 { 00142 tmp = arch_to_object(op->other_arch); 00143 /* 0 = closed, 1 = opened */ 00144 tmp->state = 0; 00145 tmp->x = op->x; 00146 tmp->y = op->y; 00147 tmp->map = op->map; 00148 tmp->level = op->level; 00149 tmp->direction = op->direction; 00150 00151 if (QUERY_FLAG(tmp, FLAG_IS_TURNABLE) || QUERY_FLAG(tmp, FLAG_ANIMATE)) 00152 { 00153 SET_ANIMATION(tmp, (NUM_ANIMATIONS(tmp) / NUM_FACINGS(tmp)) * tmp->direction + tmp->state); 00154 } 00155 00156 insert_ob_in_map(tmp, op->map, op, 0); 00157 00158 if (op->sub_type == ST1_DOOR_NORMAL) 00159 { 00160 play_sound_map(op->map, CMD_SOUND_EFFECT, "door.ogg", op->x, op->y, 0, 0); 00161 } 00162 00163 remove_ob(op); 00164 check_walk_off(op, NULL, MOVE_APPLY_VANISHED); 00165 } 00166 /* If set, we have opened a closed door - now handle autoclose */ 00167 else if (!op->last_eat) 00168 { 00169 remove_ob(op); 00170 check_walk_off(op, NULL, MOVE_APPLY_VANISHED); 00171 00172 for (tmp2 = op->inv; tmp2; tmp2 = tmp2->below) 00173 { 00174 if (tmp2 && tmp2->type == RUNE && tmp2->level) 00175 { 00176 spring_trap(tmp2, opener); 00177 } 00178 } 00179 00180 /* Mark this door as "it's open" */ 00181 op->last_eat = 1; 00182 /* Put it on active list, so it will close automatically */ 00183 op->speed = 0.1f; 00184 update_ob_speed(op); 00185 op->speed_left= -0.2f; 00186 /* Change to "open door" faces */ 00187 op->state = 1; 00188 /* Init "open" counter */ 00189 op->last_sp = op->stats.sp; 00190 00191 /* Save and clear blocksview and door_closed */ 00192 op->stats.grace = QUERY_FLAG(op, FLAG_BLOCKSVIEW) ? 1 : 0; 00193 op->last_grace = QUERY_FLAG(op, FLAG_DOOR_CLOSED) ? 1 : 0; 00194 00195 CLEAR_FLAG(op, FLAG_BLOCKSVIEW); 00196 CLEAR_FLAG(op, FLAG_DOOR_CLOSED); 00197 00198 if (QUERY_FLAG(op, FLAG_IS_TURNABLE) || QUERY_FLAG(op, FLAG_ANIMATE)) 00199 { 00200 SET_ANIMATION(op, (NUM_ANIMATIONS(op) / NUM_FACINGS(op)) * op->direction + op->state); 00201 } 00202 00203 if (op->sub_type == ST1_DOOR_NORMAL) 00204 { 00205 play_sound_map(op->map, CMD_SOUND_EFFECT, "door.ogg", op->x, op->y, 0, 0); 00206 } 00207 00208 insert_ob_in_map(op, op->map, op, 0); 00209 } 00210 00211 /* Door has FLAG_CURSED set? */ 00212 if (QUERY_FLAG(op, FLAG_CURSED)) 00213 { 00214 int i; 00215 00216 /* Let's search for a locked door on nearby tiles */ 00217 for (i = 1; i < 9; i += 2) 00218 { 00219 tmp = present(DOOR, op->map, op->x + freearr_x[i], op->y + freearr_y[i]); 00220 00221 /* Found it, slaying matches, it has FLAG_CURSED and not opened? */ 00222 if (tmp && tmp->slaying == op->slaying && QUERY_FLAG(tmp, FLAG_CURSED) && tmp->state == 0) 00223 { 00224 /* Open this door then! */ 00225 open_locked_door(tmp, opener); 00226 } 00227 } 00228 } 00229 } 00230 00234 void close_locked_door(object *op) 00235 { 00236 /* This is a bug - active speed but not marked as active */ 00237 if (!op->last_eat) 00238 { 00239 LOG(llevBug, "Door has speed but is not marked as active. (%s - map: %s (%d, %d))\n", query_name(op, NULL), op->map ? op->map->name : "(no map name!)", op->x, op->y); 00240 op->last_eat = 0; 00241 return; 00242 } 00243 00244 if (!op->map) 00245 { 00246 LOG(llevBug, "Door with speed but no map (%s - (%d, %d))\n", query_name(op, NULL), op->x, op->y); 00247 remove_ob(op); 00248 check_walk_off(op, NULL, MOVE_APPLY_VANISHED); 00249 return; 00250 } 00251 00252 /* Now check the door counter - if not <= 0 we're still open */ 00253 if (op->last_sp-- > 0) 00254 { 00255 return; 00256 } 00257 00258 /* Now we try to close the door. If the tile of the door is not blocked by 00259 * a no_pass object or a player or a monster, then we close the door. 00260 * If it is blocked - then restart a new "is open" phase. */ 00261 if (blocked(NULL, op->map, op->x, op->y, TERRAIN_ALL) & (P_NO_PASS | P_IS_ALIVE | P_IS_PLAYER)) 00262 { 00263 /* Let it open one more round. Re-init "open" counter. */ 00264 op->last_sp = op->stats.sp; 00265 } 00266 else 00267 { 00268 remove_ob(op); 00269 check_walk_off(op, NULL, MOVE_APPLY_VANISHED); 00270 00271 /* Mark this door as "it's closed" */ 00272 op->last_eat = 0; 00273 00274 /* Remove from active list */ 00275 op->speed = 0.0f; 00276 op->speed_left = 0.0f; 00277 update_ob_speed(op); 00278 00279 /* Change to "close door" faces */ 00280 op->state = 0; 00281 00282 if (op->stats.grace) 00283 { 00284 SET_FLAG(op, FLAG_BLOCKSVIEW); 00285 } 00286 else 00287 { 00288 CLEAR_FLAG(op, FLAG_BLOCKSVIEW); 00289 } 00290 00291 op->stats.grace = 0; 00292 00293 if (op->last_grace) 00294 { 00295 SET_FLAG(op, FLAG_DOOR_CLOSED); 00296 } 00297 else 00298 { 00299 CLEAR_FLAG(op, FLAG_DOOR_CLOSED); 00300 } 00301 00302 op->last_grace = 0; 00303 00304 if (QUERY_FLAG(op, FLAG_IS_TURNABLE) || QUERY_FLAG(op, FLAG_ANIMATE)) 00305 { 00306 SET_ANIMATION(op, (NUM_ANIMATIONS(op) / NUM_FACINGS(op)) * op->direction + op->state); 00307 } 00308 00309 if (op->sub_type == ST1_DOOR_NORMAL) 00310 { 00311 play_sound_map(op->map, CMD_SOUND_EFFECT, "door_close.ogg", op->x, op->y, 0, 0); 00312 } 00313 00314 insert_ob_in_map(op, op->map, op, 0); 00315 } 00316 }
1.7.4