00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "copyright.h"
00024 #include "config.h"
00025 #include <math.h>
00026 #include "mech.h"
00027 #include "mine.h"
00028 #include "p.artillery.h"
00029 #include "p.map.obj.h"
00030 #include "p.mine.h"
00031 #include "p.mech.utils.h"
00032 #include "p.btechstats.h"
00033 #include "p.template.h"
00034
00035
00036
00037
00038
00039
00040
00041 char *mine_type_names[] = {
00042 "Standard",
00043 "Inferno",
00044 "Command",
00045 "Vibra",
00046 "Trigger",
00047 NULL
00048 };
00049
00050 extern int compare_array(char *[], char *);
00051
00052 void add_mine(MAP * map, int x, int y, int dam)
00053 {
00054 mapobj *o, foo;
00055
00056 if(is_mine_hex(map, x, y)) {
00057 for(o = map->mapobj[TYPE_MINE]; o; o = o->next)
00058 if(o->x == x && o->y == y)
00059 break;
00060 if(o)
00061 return;
00062 }
00063 bzero(&foo, sizeof(foo));
00064 foo.x = x;
00065 foo.y = y;
00066 foo.datas = dam;
00067 foo.datac = MINE_STANDARD;
00068 add_mapobj(map, &map->mapobj[TYPE_MINE], &foo, 1);
00069 }
00070
00071 static void mine_damage_mechs(MAP * map, int tx, int ty, char *tomsg,
00072 char *otmsg, char *tomsg1, char *otmsg1,
00073 int dam, int heat, int nb)
00074 {
00075 blast_hit_hexes(map, dam, 5, heat, tx, ty, tomsg, otmsg, tomsg1,
00076 otmsg1, MINE_TABLE, 2, 1, 1, 1);
00077 }
00078
00079 static void update_mine(MAP * map, mapobj * mine)
00080 {
00081 int i;
00082
00083 i = mine->datas;
00084 i = i * MINE_NEXT_MODIFIER;
00085 if(i >= MINE_MIN)
00086 mine->datas = i;
00087 }
00088
00089 void make_mine_explode(MECH * mech, MAP * map, mapobj * o, int x, int y,
00090 int reason)
00091 {
00092 int cool = (o->datas >= MINE_MIN);
00093
00094 if((o->datac == MINE_TRIGGER)
00095 && reason != MINE_STEP && reason != MINE_LAND)
00096 return;
00097 if(o->datac != MINE_TRIGGER) {
00098 if(o->datac != MINE_COMMAND) {
00099 switch (reason) {
00100 case MINE_STEP:
00101 MechLOSBroadcast(mech,
00102 tprintf
00103 ("moves to %d,%d, and triggers a mine!", x,
00104 y));
00105 mech_printf(mech, MECHALL,
00106 "As you move to %d,%d, you trigger a mine!", x,
00107 y);
00108 break;
00109 case MINE_LAND:
00110 MechLOSBroadcast(mech, tprintf("triggers a mine!", x, y));
00111 mech_notify(mech, MECHALL, "You trigger a mine!");
00112 break;
00113 case MINE_DROP:
00114 case MINE_FALL:
00115 MechLOSBroadcast(mech, tprintf("triggers a mine!", x, y));
00116 mech_notify(mech, MECHALL, "You trigger a mine!");
00117 break;
00118 }
00119 } else
00120 HexLOSBroadcast(map, o->x, o->y, "A mine explodes in $H!");
00121 }
00122
00123 switch (o->datac) {
00124 case MINE_STANDARD:
00125 update_mine(map, o);
00126 mine_damage_mechs(map, o->x, o->y, "A blast of shrapnel hits you!",
00127 "is hit by shrapnel!", NULL, NULL, o->datas, 0, 0);
00128 if(!cool)
00129 mapobj_del(map, o->x, o->y, TYPE_MINE);
00130 break;
00131 case MINE_INFERNO:
00132 update_mine(map, o);
00133 mine_damage_mechs(map, o->x, o->y, "Globs of flaming gel hit you!",
00134 "is hit by globs of flaming gel!", NULL, NULL,
00135 o->datas / 3, o->datas, 0);
00136 if(!cool)
00137 mapobj_del(map, o->x, o->y, TYPE_MINE);
00138 break;
00139 case MINE_COMMAND:
00140 unset_hex_mine(map, o->x, o->y);
00141 mine_damage_mechs(map, o->x, o->y, "A blast of shrapnel hits you!",
00142 "is hit by shrapnel!",
00143 "A little blast of shrapnel hits you!",
00144 "is hit by some of the shrapnel!", o->datas, 0, 1);
00145 mapobj_del(map, o->x, o->y, TYPE_MINE);
00146 break;
00147 case MINE_TRIGGER:
00148 SendTrigger(tprintf("#%d %s activated trigger at %d,%d.",
00149 mech->mynum, GetMechID(mech), o->x, o->y));
00150
00151
00152 if(mech->mynum > 0)
00153 did_it(mech->mynum, mech->mynum, 0, NULL, 0, NULL, A_AMINETRIGGER, (char **) NULL, 0);
00154
00155 return;
00156 case MINE_VIBRA:
00157 unset_hex_mine(map, o->x, o->y);
00158 if(o->x != x || o->y != y)
00159 HexLOSBroadcast(map, o->x, o->y, "A mine explodes in $H!");
00160 mine_damage_mechs(map, o->x, o->y, "A blast of shrapnel hits you!",
00161 "is hit by shrapnel!",
00162 "A little blast of shrapnel hits you!",
00163 "is hit by some of the shrapnel!", o->datas, 0, 1);
00164 mapobj_del(map, o->x, o->y, TYPE_MINE);
00165 break;
00166 }
00167 recalculate_minefields(map);
00168 }
00169
00170
00171
00172
00173 static void possible_mine_explosion(MECH * mech, MAP * map, int x, int y,
00174 int reason)
00175 {
00176 mapobj *o, *o2;
00177 int mdis = (MechRealTons(mech) - 20) / 10;
00178 float x1, y1, x2, y2, range;
00179
00180 MapCoordToRealCoord(x, y, &x1, &y1);
00181 for(o = map->mapobj[TYPE_MINE]; o; o = o2) {
00182
00183 int real = 1;
00184
00185 o2 = o->next;
00186 if(o->x == x && o->y == y) {
00187
00188 switch (o->datac) {
00189
00190 case MINE_TRIGGER:
00191 if(o->datas > MechRealTons(mech))
00192 continue;
00193 break;
00194 case MINE_VIBRA:
00195 if(o->datai > MechRealTons(mech))
00196 continue;
00197 break;
00198 case MINE_COMMAND:
00199 mech_notify(mech, MECHALL,
00200 "You spot small bomblets lying on the ground here..");
00201 real = 0;
00202 continue;
00203 }
00204
00205 if(!real)
00206 return;
00207
00208 make_mine_explode(mech, map, o, x, y, reason);
00209
00210 } else if(VIBRO(o->datac)) {
00211
00212 if(o->datac == MINE_TRIGGER) {
00213
00214
00215 if(o->datas > (MechRealTons(mech)))
00216 continue;
00217
00218 MapCoordToRealCoord(o->x, o->y, &x2, &y2);
00219
00220
00221
00222
00223 if(nearbyintf(FindHexRange(x1, y1, x2, y2)) >
00224 ((float) o->datai))
00225 continue;
00226
00227 make_mine_explode(mech, map, o, x, y, reason);
00228
00229 } else if(o->datai < MechRealTons(mech)) {
00230
00231 if(abs(o->x - x) <= mdis && abs(o->y - y) <= mdis) {
00232
00233
00234 MapCoordToRealCoord(o->x, o->y, &x2, &y2);
00235 if((range = FindHexRange(x1, y1, x2, y2)) >
00236 (MechRealTons(mech) - o->datai) / 10)
00237 continue;
00238
00239 make_mine_explode(mech, map, o, x, y, reason);
00240 }
00241 }
00242 }
00243 }
00244 }
00245
00246 void possible_mine_poof(MECH * mech, int reason)
00247 {
00248 MAP *map = getMap(mech->mapindex);
00249 int x = MechX(mech);
00250 int y = MechY(mech);
00251
00252 if(!is_mine_hex(map, x, y))
00253 return;
00254
00255 if(MechZ(mech) > (MechRTerrain(mech) == ICE ? 0 : Elevation(map, x, y)))
00256 return;
00257
00258 possible_mine_explosion(mech, map, x, y, reason);
00259 }
00260
00261 void possibly_remove_mines(MECH * mech, int x, int y)
00262 {
00263 MAP *map = FindObjectsData(mech->mapindex);
00264
00265 if(!map)
00266 return;
00267 if(!is_mine_hex(map, x, y))
00268 return;
00269
00270
00271
00272
00273
00274 if(Roll() <= 4) {
00275 if(mapobj_del(map, x, y, TYPE_MINE)) {
00276
00277 recalculate_minefields(map);
00278 }
00279 }
00280 }
00281
00282
00283
00284
00285 static void add_mine_on_map(MAP * map, int x, int y, char type, int data)
00286 {
00287 int x1, y1;
00288 int mdis = (100 - data) / 10;
00289 int t = mdis * 3 / 2;
00290
00291 if(type == MINE_TRIGGER) {
00292
00293 float fx, fy, fx1, fy1;
00294
00295
00296 MapCoordToRealCoord(x, y, &fx, &fy);
00297
00298
00299
00300
00301 for(x1 = x - data; x1 <= x + data; x1++)
00302 for(y1 = y - data; y1 <= y + data; y1++) {
00303
00304
00305
00306
00307 MapCoordToRealCoord(x1, y1, &fx1, &fy1);
00308 if(nearbyintf(FindHexRange(fx, fy, fx1, fy1)) <=
00309 ((float) data))
00310 set_hex_mine(map, x1, y1);
00311 }
00312
00313 } else if(type >= MINE_LOW && type <= MINE_HIGH) {
00314
00315 if(VIBRO(type) && mdis) {
00316 for(x1 = x - mdis; x1 <= (x + mdis); x1++)
00317 for(y1 = y - mdis; y1 <= (y + mdis); y1++)
00318 if((abs(x1 - x) + abs(y1 - y)) <= t)
00319 if(!(x1 < 0 || y1 < 0 || x1 >= map->map_width ||
00320 y1 >= map->map_height))
00321 set_hex_mine(map, x1, y1);
00322 } else {
00323 set_hex_mine(map, x, y);
00324 }
00325 }
00326 }
00327
00328
00329 void recalculate_minefields(MAP * map)
00330 {
00331 mapobj *o;
00332
00333 clear_hex_bits(map, 1);
00334 for(o = map->mapobj[TYPE_MINE]; o; o = o->next)
00335 add_mine_on_map(map, o->x, o->y, o->datac, o->datai);
00336 }
00337
00338
00339 void map_add_mine(dbref player, void *data, char *buffer)
00340 {
00341
00342 char *args[6];
00343 int argc;
00344 int x, y, str, type, extra = 0;
00345 MAP *map = (MAP *) data;
00346 mapobj foo;
00347
00348 if(!map)
00349 return;
00350
00351 #define READINT(from,to) \
00352 DOCHECK(Readnum(to,from), "Invalid number!")
00353
00354 argc = mech_parseattributes(buffer, args, 6);
00355 DOCHECK(argc < 4 || argc > 5, "Invalid arguments!");
00356 READINT(args[0], x);
00357 READINT(args[1], y);
00358 READINT(args[3], str);
00359
00360 if(argc == 5)
00361 READINT(args[4], extra);
00362
00363 DOCHECK((type = compare_array(mine_type_names, args[2])) < 0,
00364 "Invalid mine type!");
00365 DOCHECK(!((x >= 0) && (x < map->map_width) && (y >= 0) &&
00366 (y < map->map_height)), "X,Y out of range!");
00367
00368 bzero(&foo, sizeof(foo));
00369 foo.x = x;
00370 foo.y = y;
00371 foo.datai = extra;
00372 foo.datas = str;
00373 foo.datac = type + 1;
00374 foo.obj = player;
00375 add_mapobj(map, &map->mapobj[TYPE_MINE], &foo, 1);
00376
00377 notify_printf(player,
00378 "%s mine added to (%d,%d) (strength: %d / extra: %d)",
00379 mine_type_names[type], x, y, str, extra);
00380 recalculate_minefields(map);
00381 }
00382
00383 void explode_mines(MECH * mech, int chn)
00384 {
00385 MAP *map = getMap(mech->mapindex);
00386 mapobj *o, *o2;
00387 int count = 0;
00388
00389 if(!map)
00390 return;
00391 for(o = map->mapobj[TYPE_MINE]; o; o = o2) {
00392 o2 = o->next;
00393 if(o->datac == MINE_COMMAND)
00394 if(o->datai == chn) {
00395 make_mine_explode(mech, map, o, 0, 0, 0);
00396 count++;
00397 }
00398 }
00399 if(count)
00400 recalculate_minefields(map);
00401 }
00402
00403 void show_mines_in_hex(dbref player, MECH * mech, float range, int x, int y)
00404 {
00405 MAP *map = getMap(mech->mapindex);
00406 mapobj *o;
00407
00408 DOCHECK(!is_mine_hex(map, x, y),
00409 "You see nothing else of interest in the hex, either.");
00410
00411 for(o = map->mapobj[TYPE_MINE]; o; o = o->next)
00412 if(o->x == x && o->y == y)
00413 break;
00414
00415 DOCHECK(!o, "You see nothing else of interest in the hex, either.");
00416 DOCHECK(Number(2, 9) < ((int) range),
00417 "You see nothing else of interest in the hex, either.");
00418 DOCHECK(!MadePerceptionRoll(mech, 0),
00419 "You see nothing else of interest in the hex, either.");
00420 mech_notify(mech, MECHALL,
00421 "Small bomblets litter the hex, interesting... You vaguely "
00422 "recall them from some class or other.");
00423 }