00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00027 #include <global.h>
00028 #include <sproto.h>
00029 #include <ob_methods.h>
00030 #include <ob_types.h>
00031
00036 void stop_projectile(object *op) {
00037
00038 execute_event(op, EVENT_STOP, NULL, NULL, NULL, SCRIPT_FIX_NOTHING);
00039 if (op->inv) {
00040 object *payload = op->inv;
00041
00042 remove_ob(payload);
00043 clear_owner(payload);
00044 insert_ob_in_map(payload, op->map, payload, 0);
00045 remove_ob(op);
00046 free_object(op);
00047 } else {
00048 op = fix_stopped_arrow(op);
00049 if (op)
00050 merge_ob(op, NULL);
00051 }
00052 }
00053
00062 method_ret common_process_projectile(ob_methods *context, object *op) {
00063 object *tmp;
00064 sint16 new_x, new_y;
00065 int was_reflected, mflags;
00066 mapstruct *m;
00067
00068 if (op->map == NULL) {
00069 LOG(llevError, "BUG: Projectile had no map.\n");
00070 remove_ob(op);
00071 free_object(op);
00072 return METHOD_ERROR;
00073 }
00074
00075
00076 new_x = op->x+DIRX(op);
00077 new_y = op->y+DIRY(op);
00078 was_reflected = 0;
00079
00080 m = op->map;
00081 mflags = get_map_flags(m, &m, new_x, new_y, &new_x, &new_y);
00082
00083 if (mflags&P_OUT_OF_MAP) {
00084 stop_projectile(op);
00085 return METHOD_OK;
00086 }
00087
00088
00089 if (mflags&P_IS_ALIVE) {
00090 for (tmp = GET_MAP_OB(m, new_x, new_y); tmp != NULL; tmp = tmp->above)
00091 if (QUERY_FLAG(tmp, FLAG_ALIVE))
00092 break;
00093
00094
00095
00096
00097
00098
00099
00100 if (tmp != NULL && tmp != op->owner) {
00101
00102
00103
00104
00105
00106 if (QUERY_FLAG(tmp, FLAG_REFL_MISSILE)
00107 && (rndm(0, 99)) < (90-op->level/10)) {
00108 int number = op->face->number;
00109
00110 op->direction = absdir(op->direction+4);
00111 op->state = 0;
00112 if (GET_ANIM_ID(op)) {
00113 number += 4;
00114 if (number > GET_ANIMATION(op, 8))
00115 number -= 8;
00116 op->face = &new_faces[number];
00117 }
00118 was_reflected = 1;
00119 } else {
00120
00121 op = hit_with_arrow(op, tmp);
00122 if (op == NULL)
00123 return METHOD_OK;
00124 }
00125 }
00126 }
00127
00128 if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, new_x, new_y))) {
00129 int retry = 0;
00130
00131
00132
00133
00134
00135
00136
00137 if (!QUERY_FLAG(op, FLAG_REFLECTING) || !(rndm(0, 19))) {
00138 stop_projectile(op);
00139 return METHOD_OK;
00140 } else {
00141
00142 if (op->direction&1) {
00143 op->direction = absdir(op->direction+4);
00144 retry = 1;
00145 }
00146
00147
00148
00149
00150 while (retry < 2) {
00151 int left, right, mflags;
00152 mapstruct *m1;
00153 sint16 x1, y1;
00154
00155 retry++;
00156
00157
00158
00159
00160
00161
00162 mflags = get_map_flags(op->map, &m1, op->x+freearr_x[absdir(op->direction-1)], op->y+freearr_y[absdir(op->direction-1)], &x1, &y1);
00163 left = (mflags&P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, (GET_MAP_MOVE_BLOCK(m1, x1, y1)));
00164
00165 mflags = get_map_flags(op->map, &m1, op->x+freearr_x[absdir(op->direction+1)], op->y+freearr_y[absdir(op->direction+1)], &x1, &y1);
00166 right = (mflags&P_OUT_OF_MAP) ? 0 : OB_TYPE_MOVE_BLOCK(op, (GET_MAP_MOVE_BLOCK(m1, x1, y1)));
00167
00168 if (left == right)
00169 op->direction = absdir(op->direction+4);
00170 else if (left)
00171 op->direction = absdir(op->direction+2);
00172 else if (right)
00173 op->direction = absdir(op->direction-2);
00174
00175 mflags = get_map_flags(op->map, &m1, op->x+DIRX(op), op->y+DIRY(op), &x1, &y1);
00176
00177
00178
00179
00180 if (!(mflags&P_OUT_OF_MAP)
00181 && !OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m1, x1, y1)))
00182 break;
00183 }
00184
00185
00186
00187 if (retry == 2) {
00188 stop_projectile(op);
00189 return METHOD_OK;
00190 }
00191
00192
00193 if (GET_ANIM_ID(op))
00194 SET_ANIMATION(op, op->direction);
00195 }
00196 }
00197
00198
00199 remove_ob(op);
00200 op->x = new_x;
00201 op->y = new_y;
00202
00203
00204
00205
00206 op->speed -= 0.05;
00207 insert_ob_in_map(op, m, op, 0);
00208 return METHOD_OK;
00209 }
00210
00219 method_ret common_projectile_move_on(ob_methods *context, object *trap, object *victim, object *originator) {
00220 if (common_pre_ob_move_on(trap, victim, originator) == METHOD_ERROR)
00221 return METHOD_OK;
00222 if (trap->inv == NULL) {
00223 common_post_ob_move_on(trap, victim, originator);
00224 return METHOD_OK;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233 if ((QUERY_FLAG(victim, FLAG_ALIVE) && trap->speed)
00234 && trap->owner != victim)
00235 hit_with_arrow(trap, victim);
00236 common_post_ob_move_on(trap, victim, originator);
00237 return METHOD_OK;
00238 }