Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 CrossFire, A Multiplayer game for X-windows 00003 00004 Copyright (C) 2007 Mark Wedel & Crossfire Development Team 00005 Copyright (C) 1992 Frank Tore Johansen 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software 00019 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 00021 The authors can be reached via e-mail at crossfire-devel@real-time.com 00022 */ 00023 00028 #include <global.h> 00029 #include <ob_methods.h> 00030 #include <ob_types.h> 00031 #include <sounds.h> 00032 #include <sproto.h> 00033 00034 static method_ret gate_type_process(ob_methods *context, object *op); 00035 static method_ret timed_gate_type_process(ob_methods *context, object *op); 00036 00040 void init_type_gate(void) { 00041 register_process(GATE, gate_type_process); 00042 register_process(TIMED_GATE, timed_gate_type_process); 00043 } 00044 00051 static method_ret gate_type_process(ob_methods *context, object *op) { 00052 object *tmp; 00053 00054 if (op->stats.wc < 0 || (int)op->stats.wc >= NUM_ANIMATIONS(op)) { 00055 StringBuffer *sb; 00056 char *diff; 00057 00058 LOG(llevError, "Gate error: animation was %d, max=%d\n", op->stats.wc, NUM_ANIMATIONS(op)); 00059 sb = stringbuffer_new(); 00060 dump_object(op, sb); 00061 diff = stringbuffer_finish(sb); 00062 LOG(llevError, "%s\n", diff); 00063 free(diff); 00064 op->stats.wc = 0; 00065 } 00066 00067 /* We're going down */ 00068 if (op->value) { 00069 if (--op->stats.wc <= 0) { /* Reached bottom, let's stop */ 00070 op->stats.wc = 0; 00071 if (op->arch->clone.speed) 00072 op->value = 0; 00073 else { 00074 op->speed = 0; 00075 update_ob_speed(op); 00076 } 00077 } 00078 if ((int)op->stats.wc < (NUM_ANIMATIONS(op)/2+1)) { 00079 op->move_block = 0; 00080 CLEAR_FLAG(op, FLAG_BLOCKSVIEW); 00081 update_all_los(op->map, op->x, op->y); 00082 } 00083 SET_ANIMATION(op, op->stats.wc); 00084 update_object(op, UP_OBJ_CHANGE); 00085 return METHOD_OK; 00086 } 00087 00088 /* We're going up */ 00089 00090 /* First, lets see if we are already at the top */ 00091 if ((unsigned char)op->stats.wc == (NUM_ANIMATIONS(op)-1)) { 00092 /* Check to make sure that only non pickable and non rollable 00093 * objects are above the gate. If so, we finish closing the gate, 00094 * otherwise, we fall through to the code below which should lower 00095 * the gate slightly. 00096 */ 00097 00098 for (tmp = op->above; tmp != NULL; tmp = tmp->above) 00099 if (!QUERY_FLAG(tmp, FLAG_NO_PICK) 00100 || QUERY_FLAG(tmp, FLAG_CAN_ROLL) 00101 || QUERY_FLAG(tmp, FLAG_ALIVE)) 00102 break; 00103 00104 if (tmp == NULL) { 00105 if (op->arch->clone.speed) 00106 op->value = 1; 00107 else { 00108 op->speed = 0; 00109 update_ob_speed(op); /* Reached top, let's stop */ 00110 } 00111 return METHOD_OK; 00112 } 00113 } 00114 00115 if (op->stats.food) { /* The gate is going temporarily down */ 00116 if (--op->stats.wc <= 0) { /* Gone all the way down? */ 00117 op->stats.food = 0; /* Then let's try again */ 00118 op->stats.wc = 0; 00119 } 00120 } else { /* The gate is still going up */ 00121 op->stats.wc++; 00122 00123 if ((int)op->stats.wc >= (NUM_ANIMATIONS(op))) 00124 op->stats.wc = (signed char)NUM_ANIMATIONS(op)-1; 00125 00126 /* If there is something on top of the gate, we try to roll it off. 00127 * If a player/monster, we don't roll, we just hit them with damage 00128 */ 00129 if ((int)op->stats.wc >= NUM_ANIMATIONS(op)/2) { 00130 /* Halfway or further, check blocks */ 00131 /* First, get the top object on the square. */ 00132 for (tmp = op->above; tmp != NULL && tmp->above != NULL; tmp = tmp->above) 00133 ; 00134 00135 if (tmp != NULL) { 00136 if (QUERY_FLAG(tmp, FLAG_ALIVE)) { 00137 hit_player(tmp, random_roll(1, op->stats.dam, tmp, PREFER_LOW), op, AT_PHYSICAL, 1); 00138 if (tmp->type == PLAYER) 00139 draw_ext_info_format(NDI_UNIQUE, 0, tmp, MSG_TYPE_VICTIM, MSG_TYPE_VICTIM_WAS_HIT, 00140 "You are crushed by the %s!", 00141 "You are crushed by the %s!", 00142 op->name); 00143 } else 00144 /* If the object is not alive, and the object either can 00145 * be picked up or the object rolls, move the object 00146 * off the gate. 00147 */ 00148 if (!QUERY_FLAG(tmp, FLAG_ALIVE) 00149 && (!QUERY_FLAG(tmp, FLAG_NO_PICK) || QUERY_FLAG(tmp, FLAG_CAN_ROLL))) { 00150 /* If it has speed, it should move itself, otherwise: */ 00151 int i = find_free_spot(tmp, op->map, op->x, op->y, 1, 9); 00152 00153 /* If there is a free spot, move the object someplace */ 00154 if (i != -1) { 00155 remove_ob(tmp); 00156 tmp->x += freearr_x[i], 00157 tmp->y += freearr_y[i]; 00158 insert_ob_in_map(tmp, op->map, op, 0); 00159 } 00160 } 00161 } 00162 00163 /* See if there is still anything blocking the gate */ 00164 for (tmp = op->above; tmp != NULL; tmp = tmp->above) 00165 if (!QUERY_FLAG(tmp, FLAG_NO_PICK) 00166 || QUERY_FLAG(tmp, FLAG_CAN_ROLL) 00167 || QUERY_FLAG(tmp, FLAG_ALIVE)) 00168 break; 00169 00170 /* IF there is, start putting the gate down */ 00171 if (tmp) { 00172 op->stats.food = 1; 00173 } else { 00174 op->move_block = MOVE_ALL; 00175 if (!op->arch->clone.stats.ac) 00176 SET_FLAG(op, FLAG_BLOCKSVIEW); 00177 update_all_los(op->map, op->x, op->y); 00178 } 00179 } /* gate is halfway up */ 00180 00181 SET_ANIMATION(op, op->stats.wc); 00182 update_object(op, UP_OBJ_CHANGE); 00183 } /* gate is going up */ 00184 00185 return METHOD_OK; 00186 } 00187 00198 static method_ret timed_gate_type_process(ob_methods *context, object *op) { 00199 int v = op->value; 00200 00201 if (op->stats.sp) { 00202 gate_type_process(context, op); 00203 if (op->value != v) /* change direction ? */ 00204 op->stats.sp = 0; 00205 return METHOD_OK; 00206 } 00207 if (--op->stats.hp <= 0) { /* keep gate down */ 00208 gate_type_process(context, op); 00209 if (op->value != v) { /* ready ? */ 00210 op->speed = 0; 00211 update_ob_speed(op); 00212 } 00213 } 00214 return METHOD_OK; 00215 }