00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <math.h>
00014 #include <sys/file.h>
00015
00016 #include "mech.h"
00017 #include "mech.events.h"
00018 #include "create.h"
00019 #include "p.mech.utils.h"
00020 #include "p.mine.h"
00021 #include "p.btechstats.h"
00022
00023 #define FIRESPEED(map) (MAX(20,60 - map->windspeed))
00024
00025 static char *map_types[] =
00026 { "FIRE", "SMOKE", "DECO", "MINE", "BUILDING", "LEAVE", "ENTRA",
00027 "LINKED", "TBITS", "BLZ", NULL
00028 };
00029
00030 mapobj *free_mapobjs = NULL;
00031
00032 #define MAPOBJSTART_MAGICNUM 27
00033 #define MAPOBJEND_MAGICNUM 39
00034
00035 mapobj *next_mapobj(mapobj * m)
00036 {
00037 return m->next;
00038 }
00039
00040 mapobj *first_mapobj(MAP * map, int type)
00041 {
00042 return map->mapobj[type];
00043 }
00044
00045 void save_mapobjs(FILE * f, MAP * map)
00046 {
00047 #define outbyte(a) tmpb=(a);fwrite(&tmpb, 1, 1, f);
00048 int i;
00049 unsigned char tmpb;
00050 mapobj *tmp;
00051
00052 outbyte(MAPOBJSTART_MAGICNUM);
00053 for(i = 0; i < NUM_MAPOBJTYPES; i++)
00054 if(map->mapobj[i]) {
00055 if(i == TYPE_BITS) {
00056 tmp = map->mapobj[i];
00057 map_save_bits(f, map, tmp);
00058 } else
00059 for(tmp = map->mapobj[i]; tmp; tmp = tmp->next) {
00060 outbyte(i + 1);
00061 fwrite(tmp, sizeof(mapobj), 1, f);
00062 }
00063 }
00064 outbyte(0);
00065 outbyte(MAPOBJEND_MAGICNUM);
00066 }
00067
00068 int find_entrance(MAP * map, char dir, int *x, int *y)
00069 {
00070 mapobj *tmp;
00071
00072 for(tmp = first_mapobj(map, TYPE_ENTRANCE); tmp; tmp = next_mapobj(tmp))
00073 if(!dir || tmp->datac == dir) {
00074 *x = tmp->x;
00075 *y = tmp->y;
00076 return 1;
00077 }
00078 return 0;
00079 }
00080
00081 char *structure_name(mapobj * mapo)
00082 {
00083 static char buf[MBUF_SIZE];
00084
00085 sprintf(buf, "the %s", Name(mapo->obj));
00086 return buf;
00087 }
00088
00089 mapobj *find_entrance_by_target(MAP * map, dbref target)
00090 {
00091 mapobj *tmp;
00092
00093 for(tmp = first_mapobj(map, TYPE_BUILD); tmp; tmp = next_mapobj(tmp))
00094 if(tmp->obj == target)
00095 return tmp;
00096 return NULL;
00097 }
00098
00099 mapobj *find_entrance_by_xy(MAP * map, int x, int y)
00100 {
00101 mapobj *tmp;
00102
00103 for(tmp = first_mapobj(map, TYPE_BUILD); tmp; tmp = next_mapobj(tmp))
00104 if(tmp->x == x && tmp->y == y)
00105 return tmp;
00106 return NULL;
00107 }
00108
00109 mapobj *find_mapobj(MAP * map, int x, int y, int type)
00110 {
00111 mapobj *tmp;
00112 int i;
00113
00114 if(type >= 0) {
00115 for(tmp = first_mapobj(map, type); tmp; tmp = next_mapobj(tmp))
00116 if(tmp->x == x && tmp->y == y)
00117 return tmp;
00118 } else {
00119 for(i = 0; i < NUM_MAPOBJTYPES; i++)
00120 for(tmp = first_mapobj(map, i); tmp; tmp = next_mapobj(tmp))
00121 if(tmp->x == x && tmp->y == y)
00122 return tmp;
00123 }
00124 return NULL;
00125 }
00126
00127 char find_decorations(MAP * map, int x, int y)
00128 {
00129 int i;
00130 mapobj *m;
00131
00132 for(i = 0; i <= TYPE_LAST_DEC; i++) {
00133 for(m = first_mapobj(map, i); m; m = next_mapobj(m))
00134 if(m->x == x && m->y == y)
00135 return m->datac;
00136 }
00137 return 0;
00138 }
00139
00140 void del_mapobj(MAP * map, mapobj * mapob, int type, int zap)
00141 {
00142
00143 struct mapobj_struct *tmp;
00144
00145 if(!(map->flags & MAPFLAG_MAPO))
00146 return;
00147 if(map->mapobj[type] != mapob) {
00148 for(tmp = map->mapobj[type]; tmp->next && tmp->next != mapob;
00149 tmp = tmp->next);
00150 if(!tmp->next)
00151 return;
00152 tmp->next = mapob->next;
00153 } else
00154 map->mapobj[type] = mapob->next;
00155
00156 if(type <= TYPE_LAST_DEC) {
00157
00158 if(!(zap & 2))
00159 SetTerrain(map, mapob->x, mapob->y, mapob->datac);
00160 if(zap)
00161 StopDec(mapob);
00162 }
00163 mapob->next = free_mapobjs;
00164 free_mapobjs = mapob;
00165 }
00166
00167 void del_mapobjst(MAP * map, int type)
00168 {
00169 if(!(map->flags & MAPFLAG_MAPO))
00170 return;
00171 while (map->mapobj[type])
00172 del_mapobj(map, map->mapobj[type], type, 3);
00173 }
00174
00175 void del_mapobjs(MAP * map)
00176 {
00177 int i;
00178
00179 for(i = 0; i < NUM_MAPOBJTYPES; i++)
00180 del_mapobjst(map, i);
00181 if(map->flags & MAPFLAG_MAPO)
00182 map->flags &= ~MAPFLAG_MAPO;
00183 }
00184
00185 mapobj *add_mapobj(MAP * map, mapobj ** to, mapobj * from, int flag)
00186 {
00187 mapobj *realto;
00188
00189 map->flags |= MAPFLAG_MAPO;
00190 from->next = *to;
00191 if(!free_mapobjs) {
00192 Create(realto, mapobj, 1);
00193 } else {
00194 realto = free_mapobjs;
00195 free_mapobjs = realto->next;
00196 }
00197 bcopy(from, realto, sizeof(mapobj));
00198 *to = realto;
00199 return realto;
00200 }
00201
00202 static void smoke_dissipation_event(MUXEVENT * e)
00203 {
00204 MAP *map = (MAP *) e->data;
00205 mapobj *o = (mapobj *) e->data2;
00206
00207 del_mapobj(map, o, TYPE_SMOKE, 0);
00208 }
00209
00210 static void fire_dissipation_event(MUXEVENT * e)
00211 {
00212 MAP *map = (MAP *) e->data;
00213 mapobj *o = (mapobj *) e->data2;
00214 int x, y;
00215
00216 x = o->x;
00217 y = o->y;
00218 del_mapobj(map, o, TYPE_FIRE, 0);
00219 if(IsForestHex(map, x, y)) {
00220 if(Number(1, 6) < 3)
00221 SetTerrain(map, x, y, GRASSLAND);
00222 else
00223 SetTerrain(map, x, y, ROUGH);
00224 }
00225 }
00226
00227 int FindXEven(wind, x)
00228 int wind;
00229 int x;
00230
00231 {
00232 switch (wind) {
00233 case 0:
00234 if(x == 0)
00235 return 0;
00236 if(x == 1)
00237 return -1;
00238 return 1;
00239 case 60:
00240 if(x == 0)
00241 return 1;
00242 if(x == 1)
00243 return 0;
00244 return 1;
00245 case 120:
00246 if(x == 0)
00247 return 1;
00248 if(x == 1)
00249 return 1;
00250 return 0;
00251 case 180:
00252 if(x == 0)
00253 return 0;
00254 if(x == 1)
00255 return 1;
00256 return -1;
00257 case 240:
00258 return x - 1;
00259 case 300:
00260 if(x == 0)
00261 return -1;
00262 if(x == 1)
00263 return 0;
00264 return -1;
00265 }
00266 return 0;
00267 }
00268
00269 int FindYEven(wind, y)
00270 int wind;
00271 int y;
00272
00273 {
00274 switch (wind) {
00275 case 0:
00276 if(y == 0)
00277 return -1;
00278 if(y == 1)
00279 return 0;
00280 return 0;
00281 case 60:
00282 if(y == 0)
00283 return 0;
00284 if(y == 1)
00285 return -1;
00286 return 1;
00287 case 120:
00288 if(y == 0)
00289 return 1;
00290 if(y == 1)
00291 return 0;
00292 return 1;
00293 case 180:
00294 return 1;
00295 case 240:
00296 if(y == 0)
00297 return 1;
00298 if(y == 1)
00299 return 1;
00300 return 0;
00301 case 300:
00302 if(y == 0)
00303 return 0;
00304 if(y == 1)
00305 return -1;
00306 return 1;
00307 }
00308 return 0;
00309 }
00310
00311 int FindXOdd(wind, x)
00312 int wind;
00313 int x;
00314
00315 {
00316 switch (wind) {
00317 case 0:
00318 if(x == 0)
00319 return 0;
00320 if(x == 1)
00321 return 1;
00322 return -1;
00323 case 60:
00324 if(x == 0)
00325 return 1;
00326 if(x == 1)
00327 return 0;
00328 return 1;
00329 case 120:
00330 if(x == 0)
00331 return 1;
00332 if(x == 1)
00333 return 1;
00334 return 0;
00335 case 180:
00336 if(x == 0)
00337 return 0;
00338 if(x == 1)
00339 return 1;
00340 return -1;
00341 case 240:
00342 return x - 1;
00343 case 300:
00344 if(x == 0)
00345 return -1;
00346 if(x == 1)
00347 return -1;
00348 return 0;
00349 }
00350 return 0;
00351 }
00352
00353 int FindYOdd(wind, y)
00354 int wind;
00355 int y;
00356
00357 {
00358 switch (wind) {
00359 case 0:
00360 if(y == 0)
00361 return -1;
00362 if(y == 1)
00363 return -1;
00364 return -1;
00365 case 60:
00366 if(y == 0)
00367 return -1;
00368 if(y == 1)
00369 return -1;
00370 return 0;
00371 case 120:
00372 if(y == 0)
00373 return 0;
00374 if(y == 1)
00375 return -1;
00376 return 1;
00377 case 180:
00378 if(y == 0)
00379 return 1;
00380 if(y == 1)
00381 return 0;
00382 return 0;
00383 case 240:
00384 if(y == 0)
00385 return 0;
00386 if(y == 1)
00387 return 1;
00388 return -1;
00389 case 300:
00390 if(y == 0)
00391 return -1;
00392 if(y == 1)
00393 return 0;
00394 return -1;
00395 }
00396 return 0;
00397 }
00398
00399 #define NUM_SPREAD_HEX 4
00400
00401 void CheckForFire(MAP * map, int x[], int y[])
00402 {
00403 int i;
00404
00405 for(i = 0; i < NUM_SPREAD_HEX; i++) {
00406 if(x[i] < 0 || y[i] < 0)
00407 continue;
00408
00409 if(IsForestHex(map, x[i], y[i]))
00410 add_decoration(map, x[i], y[i], TYPE_FIRE, FIRE, FIRE_DURATION);
00411 }
00412 }
00413
00414 void CheckForSmoke(MAP * map, int x[], int y[])
00415 {
00416 int i;
00417
00418 for(i = 0; i < NUM_SPREAD_HEX; i++) {
00419 if(x[i] < 0 || y[i] < 0)
00420 continue;
00421 if(find_decorations(map, x[i], y[i]))
00422 continue;
00423
00424 switch (GetTerrain(map, x[i], y[i])) {
00425 case BUILDING:
00426 case WALL:
00427 continue;
00428 default:
00429 break;
00430 }
00431 add_decoration(map, x[i], y[i], TYPE_SMOKE, SMOKE, SMOKE_DURATION);
00432 }
00433 }
00434
00435 static void FindMyCoord(MAP * map, int tx, int ty, int i, int wdir, int *x,
00436 int *y)
00437 {
00438 int dx, dy;
00439
00440 wdir = (((wdir + 30) / 60) * 60) % 360;
00441 if(tx % 2) {
00442 dx = tx + FindXOdd(wdir, i);
00443 dy = ty + FindYOdd(wdir, i);
00444 } else {
00445 dx = tx + FindXEven(wdir, i);
00446 dy = ty + FindYEven(wdir, i);
00447 }
00448 if(dx < 0 || dy < 0 || dx >= map->map_width || dy >= map->map_height) {
00449 *x = -1;
00450 *y = -1;
00451 return;
00452 }
00453 *x = dx;
00454 *y = dy;
00455 }
00456
00457 static void fire_spreading_event(MUXEVENT * e)
00458 {
00459 MAP *map = (MAP *) e->data;
00460 mapobj *o = (mapobj *) e->data2;
00461 int x, y, loop;
00462 int flaggo;
00463 int new_fire_hex_x[4];
00464 int new_fire_hex_y[4];
00465 int new_smoke_hex_x[4];
00466 int new_smoke_hex_y[4];
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 x = o->x;
00484 y = o->y;
00485 for(loop = 0; loop < 3; loop++) {
00486 new_fire_hex_x[loop] = -1;
00487 new_fire_hex_y[loop] = -1;
00488 FindMyCoord(map, x, y, loop, map->winddir, &new_smoke_hex_x[loop],
00489 &new_smoke_hex_y[loop]);
00490 }
00491 new_fire_hex_x[3] = -1;
00492 new_fire_hex_y[3] = -1;
00493 FindMyCoord(map, new_smoke_hex_x[0], new_smoke_hex_y[0], 0,
00494 map->winddir, &new_smoke_hex_x[3], &new_smoke_hex_y[3]);
00495 #define Spr(n,ch) \
00496 if(Roll() >= ch && Number(1,60) <= map->windspeed) \
00497 { \
00498 new_fire_hex_x[n] = new_smoke_hex_x[n]; \
00499 new_fire_hex_y[n] = new_smoke_hex_y[n]; \
00500 }
00501 Spr(0, 9);
00502 Spr(1, 11);
00503 Spr(2, 11);
00504 Spr(3, 12);
00505 #undef Spr
00506 CheckForSmoke(map, new_smoke_hex_x, new_smoke_hex_y);
00507 CheckForFire(map, new_fire_hex_x, new_fire_hex_y);
00508 flaggo = (o->datas -= FIRESPEED(map));
00509 if(flaggo > FIRESPEED(map))
00510 MAPEVENT(map, EVENT_DECORATION, fire_spreading_event,
00511 FIRESPEED(map), o);
00512 else
00513 MAPEVENT(map, EVENT_DECORATION, fire_dissipation_event, flaggo, o);
00514 }
00515
00516 void add_decoration(MAP * map, int x, int y, int type, char data, int flaggo)
00517 {
00518 mapobj foo;
00519 mapobj *tmpo;
00520
00521 bzero(&foo, sizeof(mapobj));
00522 foo.x = x;
00523 foo.y = y;
00524 foo.datac = GetRTerrain(map, x, y);
00525
00526 {
00527 mapobj *m, *m2;
00528 int i;
00529
00530 for(i = 0; i <= TYPE_LAST_DEC; i++) {
00531 for(m = first_mapobj(map, i); m; m = m2) {
00532 m2 = next_mapobj(m);
00533 if(m->x == x && m->y == y)
00534 del_mapobj(map, m, i, 1);
00535 }
00536 }
00537 }
00538 SetTerrain(map, x, y, data);
00539 foo.datas = (short) flaggo;
00540 tmpo = add_mapobj(map, &map->mapobj[type], &foo, 1);
00541 if(flaggo) {
00542 if(type == TYPE_SMOKE)
00543 MAPEVENT(map, EVENT_DECORATION, smoke_dissipation_event,
00544 flaggo, tmpo);
00545 if(type == TYPE_FIRE) {
00546 foo.datas = foo.datas * FIRESPEED(map) * 4 / 3 / 60;
00547 foo.datas = MAX(foo.datas, FIRESPEED(map) * 2);
00548 MAPEVENT(map, EVENT_DECORATION, fire_spreading_event,
00549 FIRESPEED(map), tmpo);
00550 }
00551 }
00552 }
00553
00554 void load_mapobjs(FILE * f, MAP * map)
00555 {
00556 unsigned char tmpb;
00557 int i;
00558 mapobj tmp;
00559
00560 fread(&tmpb, 1, 1, f);
00561 if(tmpb != MAPOBJSTART_MAGICNUM) {
00562 fprintf(stderr, "Error: No mapobjstart found!");
00563 return;
00564 }
00565
00566 for(i = 0; i < NUM_MAPOBJTYPES; i++)
00567 map->mapobj[i] = NULL;
00568 fread(&tmpb, 1, 1, f);
00569 while (tmpb && !feof(f)) {
00570 if((tmpb - 1) == TYPE_BITS)
00571 map_load_bits(f, map);
00572 else {
00573 fread(&tmp, sizeof(mapobj), 1, f);
00574 add_mapobj(map, &map->mapobj[tmpb - 1], &tmp, 0);
00575 if((tmpb - 1) == TYPE_BUILD)
00576 possibly_start_building_regen(tmp.obj);
00577 }
00578 fread(&tmpb, 1, 1, f);
00579 }
00580 fread(&tmpb, 1, 1, f);
00581 if(tmpb != MAPOBJEND_MAGICNUM)
00582 fprintf(stderr, "Error: No mapobjend found!");
00583 }
00584
00585 void list_mapobjs(dbref player, MAP * map)
00586 {
00587 mapobj *tmp;
00588 int i;
00589
00590 notify(player, "X Y Type obj dc ds di");
00591 notify(player, "--------------------------------------------");
00592 for(i = 0; i < NUM_MAPOBJTYPES; i++)
00593 for(tmp = first_mapobj(map, i); tmp; tmp = next_mapobj(tmp)) {
00594 if(i == TYPE_BITS)
00595 notify(player, "--- MAP/HANGAR INFORMATION OBJECT ---");
00596 else
00597 notify_printf(player, "%-3d %-3d %-5s %-5d %-4d %-6d %d",
00598 tmp->x, tmp->y, map_types[i], (int) tmp->obj,
00599 tmp->datac, tmp->datas, tmp->datai);
00600 }
00601 notify(player, "--------------------------------------------");
00602 }
00603
00604 void map_addfire(dbref player, void *data, char *buffer)
00605 {
00606
00607 MAP *map = (MAP *) data;
00608 char *args[4];
00609 int x, y, d;
00610
00611 if(mech_parseattributes(buffer, args, 3) != 3) {
00612 notify(player,
00613 "Error: Invalid number of attributes to addfire command.");
00614 return;
00615 }
00616 x = atoi(args[0]);
00617 y = atoi(args[1]);
00618 d = atoi(args[2]);
00619 add_decoration(map, x, y, TYPE_FIRE, FIRE, d);
00620 notify_printf(player, "Added: Fire at (%d,%d) with duration of %ds.",
00621 x, y, d);
00622 }
00623
00624 void map_addsmoke(dbref player, void *data, char *buffer)
00625 {
00626 MAP *map = (MAP *) data;
00627 char *args[4];
00628 int x, y, d;
00629
00630 if(mech_parseattributes(buffer, args, 3) != 3) {
00631 notify(player,
00632 "Error: Invalid number of attributes to addsmoke command.");
00633 return;
00634 }
00635 x = atoi(args[0]);
00636 y = atoi(args[1]);
00637 d = atoi(args[2]);
00638 add_decoration(map, x, y, TYPE_SMOKE, SMOKE, d);
00639 notify_printf(player, "Added: Smoke at (%d,%d) with duration of %ds.",
00640 x, y, d);
00641 }
00642
00643
00644 void map_add_block(dbref player, void *data, char *buffer)
00645 {
00646 char *args[4];
00647 int argc;
00648 int x, y, str;
00649 MAP *map = (MAP *) data;
00650 mapobj foo;
00651 int team = 0;
00652
00653 if(!map)
00654 return;
00655 #define READINT(from,to) \
00656 DOCHECK(Readnum(to,from), "Invalid number!")
00657 argc = mech_parseattributes(buffer, args, 4);
00658 DOCHECK(argc < 2 || argc > 4, "Invalid arguments!");
00659 READINT(args[0], x);
00660 READINT(args[1], y);
00661 READINT(args[2], str);
00662 if(argc == 4)
00663 READINT(args[3], team);
00664 bzero(&foo, sizeof(mapobj));
00665 foo.x = x;
00666 foo.y = y;
00667 foo.datai = str;
00668 foo.obj = player;
00669 foo.datac = team;
00670 add_mapobj(map, &map->mapobj[TYPE_B_LZ], &foo, 1);
00671 notify_printf(player,
00672 "Landingzone-block added to %d,%d (distance: %d)", x, y,
00673 str);
00674 }
00675
00676 int is_blocked_lz(MECH * mech, MAP * map, int x, int y)
00677 {
00678 mapobj *o;
00679 float fx, fy;
00680 float tx, ty;
00681
00682 MapCoordToRealCoord(x, y, &fx, &fy);
00683 for(o = first_mapobj(map, TYPE_B_LZ); o; o = next_mapobj(o)) {
00684 if(abs(x - o->x) > o->datai || abs(y - o->y) > o->datai)
00685 continue;
00686 if(o->datac && o->datac == MechTeam(mech))
00687 continue;
00688 MapCoordToRealCoord(o->x, o->y, &tx, &ty);
00689 if(FindHexRange(fx, fy, tx, ty) <= o->datai)
00690 return 1;
00691 }
00692 return 0;
00693 }
00694
00695 void map_setlinked(dbref player, void *data, char *buffer)
00696 {
00697 MAP *map = (MAP *) data;
00698 mapobj foo;
00699
00700 bzero(&foo, sizeof(mapobj));
00701 foo.datac = 1;
00702 add_mapobj(map, &map->mapobj[TYPE_LINKED], &foo, 1);
00703 notify_printf(player, "Map set to linked.");
00704 }
00705
00706 int mapobj_del(MAP * map, int x, int y, int tt)
00707 {
00708 int count = 0;
00709 mapobj *foo, *foo2;
00710
00711 for(foo = first_mapobj(map, tt); foo; foo = foo2) {
00712 foo2 = next_mapobj(foo);
00713 if(foo->x == x && foo->y == y) {
00714 del_mapobj(map, foo, tt, 1);
00715 count++;
00716 }
00717 }
00718 return count;
00719 }
00720
00721 void map_delobj(dbref player, void *data, char *buffer)
00722 {
00723 MAP *map = (MAP *) data;
00724 char *args[5];
00725 mapobj *foo, *foo2;
00726 int tt, count = 0, mdel = 0;
00727 int x, y;
00728
00729 switch (mech_parseattributes(buffer, args, 3)) {
00730 case 0:
00731 notify(player,
00732 "Error: Invalid number of attributes to delobj command.");
00733 return;
00734 case 1:
00735 DOCHECK((tt = listmatch(map_types, args[0])) < 0, "Invalid type!");
00736 for(foo = map->mapobj[tt]; foo; foo = foo2) {
00737 foo2 = next_mapobj(foo);
00738 del_mapobj(map, foo, tt, 1);
00739 count++;
00740 }
00741 notify_printf(player, "%d objects deleted!", count);
00742 if(tt == TYPE_MINE)
00743 mdel = 1;
00744 break;
00745 case 2:
00746 x = atoi(args[0]);
00747 y = atoi(args[1]);
00748 for(tt = 0; tt < NUM_MAPOBJTYPES; tt++)
00749 for(foo = first_mapobj(map, tt); foo; foo = foo2) {
00750 foo2 = next_mapobj(foo);
00751 if(foo->x == x && foo->y == y) {
00752 if(tt == TYPE_MINE)
00753 mdel = 1;
00754 del_mapobj(map, foo, tt, 1);
00755 count++;
00756 }
00757 }
00758 notify_printf(player, "%d objects at (%d,%d) deleted.", count, x, y);
00759 break;
00760 case 3:
00761 DOCHECK((tt = listmatch(map_types, args[0])) < 0, "Invalid type!");
00762 x = atoi(args[1]);
00763 y = atoi(args[2]);
00764 for(foo = first_mapobj(map, tt); foo; foo = foo2) {
00765 foo2 = next_mapobj(foo);
00766 if(foo->x == x && foo->y == y) {
00767 if(tt == TYPE_MINE)
00768 mdel = 1;
00769 del_mapobj(map, foo, tt, 1);
00770 count++;
00771 }
00772 }
00773 notify_printf(player, "%d %s at (%d,%d) deleted.", count,
00774 map_types[tt], x, y);
00775 break;
00776 default:
00777 notify(player, "Invalid number of arguments!");
00778 return;
00779 }
00780 if(mdel)
00781 recalculate_minefields(map);
00782 }
00783
00784 int update_stats[3];
00785
00786 #define addstat(a) update_stats[(a)]++
00787
00788 struct {
00789 int x, y;
00790 char dir;
00791 } dirtable[4] = {
00792 {
00793 1, 0, 'n'}, {
00794 2, 1, 'e'}, {
00795 1, 2, 's'}, {
00796 0, 1, 'w'}
00797 };
00798
00799 void recursively_updatelinks(dbref from, dbref loc);
00800
00801 int parse_coord(MAP * map, int dir, char *data, int *x, int *y)
00802 {
00803 int tx, ty, tox, toy;
00804 int doh;
00805
00806 if(strchr(data, ',')) {
00807 if(sscanf(data, "%d,%d", x, y) == 2)
00808 return 1;
00809 return 0;
00810 }
00811 doh = atoi(data);
00812 if(doh < 0)
00813 return 0;
00814 tox = dirtable[dir].x;
00815 toy = dirtable[dir].y;
00816 tx = (map->map_width * tox) / 2;
00817 if(tx >= map->map_width)
00818 tx = map->map_width - 1;
00819 ty = (map->map_height * toy) / 2;
00820 if(ty >= map->map_height)
00821 ty = map->map_height - 1;
00822 if(tox == 1)
00823 ty += (toy > 1) ? (0 - doh) : (doh);
00824 if(toy == 1)
00825 tx += (tox > 1) ? (0 - doh) : (doh);
00826 if(tx < 0)
00827 tx = 0;
00828 if(ty < 0)
00829 ty = 0;
00830 if(tx >= map->map_width)
00831 tx = (map->map_width - 1);
00832 if(ty >= map->map_height)
00833 ty = (map->map_height - 1);
00834 *x = tx;
00835 *y = ty;
00836 return 1;
00837 }
00838
00839 void add_entrances(dbref loc, MAP * map, char *data)
00840 {
00841 char *buf;
00842 char *args[4];
00843 int x, y, i;
00844 mapobj foo;
00845
00846 bzero(&foo, sizeof(mapobj));
00847
00848 buf = alloc_mbuf("add_entrances");
00849
00850 strcpy(buf, data);
00851 if(mech_parseattributes(buf, args, 4) == 4) {
00852 for(i = 0; i < 4; i++)
00853 if((parse_coord(map, i, args[i], &x, &y))) {
00854 foo.datac = dirtable[i].dir;
00855 foo.x = x;
00856 foo.y = y;
00857 add_mapobj(map, &map->mapobj[TYPE_ENTRANCE], &foo, 1);
00858 addstat(2);
00859 }
00860 }
00861 free_mbuf(buf);
00862 }
00863
00864 void add_links(dbref loc, MAP * map, char *data)
00865 {
00866 char *buf;
00867 char *args[500];
00868 int i, found, targ;
00869 char *tmps;
00870 int x, y;
00871 mapobj foo;
00872
00873 bzero(&foo, sizeof(mapobj));
00874
00875 buf = alloc_lbuf("add_links");
00876
00877 strcpy(buf, data);
00878 if((found = mech_parseattributes(buf, args, 500)) > 0)
00879 for(i = 0; i < found; i++) {
00880 targ = atoi(args[i]);
00881 if(targ < 0 || !(FindObjectsData(targ)) || targ == loc)
00882 continue;
00883 tmps = silly_atr_get(targ, A_BUILDCOORD);
00884 if(!tmps)
00885 continue;
00886 if(sscanf(tmps, "%d,%d", &x, &y) != 2)
00887 continue;
00888 if(x < 0 || x >= map->map_width || y < 0 || y >= map->map_height)
00889 continue;
00890 set_hex_enterable(map, x, y);
00891 foo.x = x;
00892 foo.y = y;
00893 foo.obj = targ;
00894 add_mapobj(map, &map->mapobj[TYPE_BUILD], &foo, 1);
00895 addstat(0);
00896 recursively_updatelinks(loc, targ);
00897 }
00898 free_lbuf(buf);
00899 }
00900
00901 void recursively_updatelinks(dbref from, dbref loc)
00902 {
00903 MAP *map;
00904 mapobj foo;
00905 char *tmps;
00906
00907 bzero(&foo, sizeof(mapobj));
00908 if(!(map = getMap(loc)))
00909 return;
00910 clear_hex_bits(map, 2);
00911 if(from >= 0) {
00912 map->onmap = from;
00913
00914 del_mapobjst(map, TYPE_LEAVE);
00915 addstat(1);
00916 foo.obj = from;
00917 add_mapobj(map, &map->mapobj[TYPE_LEAVE], &foo, 0);
00918 del_mapobjst(map, TYPE_ENTRANCE);
00919
00920
00921 tmps = silly_atr_get(loc, A_BUILDENTRANCE);
00922 if(tmps) {
00923
00924
00925
00926
00927 add_entrances(loc, map, tmps);
00928 }
00929 }
00930 del_mapobjst(map, TYPE_BUILD);
00931 tmps = silly_atr_get(loc, A_BUILDLINKS);
00932 if(tmps)
00933 add_links(loc, map, tmps);
00934 }
00935
00936 void map_updatelinks(dbref player, void *data, char *buffer)
00937 {
00938 dbref ourloc;
00939
00940 ourloc = Location(player);
00941 bzero(update_stats, sizeof(update_stats));
00942 recursively_updatelinks(NOTHING, ourloc);
00943 notify_printf(player,
00944 "Updated %d BUILD objs, %d LEAVE objs, %d ENTRANCE objs.",
00945 update_stats[0], update_stats[1], update_stats[2]);
00946 }
00947
00948 int map_linked(dbref mapobj)
00949 {
00950 MAP *map = getMap(mapobj);
00951
00952 if(!map)
00953 return 0;
00954 return (first_mapobj(map, TYPE_LINKED)) ? 1 : 0;
00955 }
00956
00957 static int get_building_cf(dbref d, int *i1, int *i2)
00958 {
00959 MAP *map;
00960
00961 if(!(map = getMap(d)))
00962 return 0;
00963 *i1 = map->cf;
00964 *i2 = map->cfmax;
00965 return map->cf;
00966 }
00967
00968 int get_cf(dbref d)
00969 {
00970 int cf, max = 0;
00971
00972 if(!(get_building_cf(d, &cf, &max)))
00973 if(max <= 0)
00974 return -1;
00975 return cf;
00976 }
00977
00978 static void set_building_cf(dbref obj, int i1, int i2)
00979 {
00980 MAP *map;
00981
00982 if(!(map = getMap(obj)))
00983 return;
00984 map->cf = i1;
00985 map->cfmax = i2;
00986 }
00987
00988 static void building_regen_event(MUXEVENT * e)
00989 {
00990 #ifdef BUILDINGS_REPAIR_THEMSELVES
00991 dbref d = (dbref) e->data;
00992 int cf, max;
00993
00994 if(!get_building_cf(d, &cf, &max))
00995 return;
00996 cf = MIN(cf + BUILDING_REPAIR_AMOUNT, max);
00997 set_building_cf(d, cf, max);
00998 if(cf != max)
00999 OBJEVENT(d, EVENT_BREGEN, building_regen_event,
01000 BUILDING_REPAIR_DELAY, NULL);
01001 #endif
01002 }
01003
01004 static void building_rebuild_event(MUXEVENT * e)
01005 {
01006 #ifdef BUILDINGS_REBUILD_FROM_DESTRUCTION
01007 dbref d = (dbref) e->data;
01008 int cf = 0, max = 0;
01009
01010 if(get_building_cf(d, &cf, &max))
01011 return;
01012 if(max <= 0)
01013 return;
01014 set_building_cf(d, 1, max);
01015 #endif
01016 }
01017
01018 void possibly_start_building_regen(dbref obj)
01019 {
01020 int f, t;
01021
01022 if(!get_building_cf(obj, &f, &t))
01023 return;
01024 if(f == t)
01025 return;
01026 if(!f)
01027 OBJEVENT(obj, EVENT_BREBUILD, building_rebuild_event,
01028 BUILDING_DREBUILD_DELAY, NULL);
01029 else
01030 OBJEVENT(obj, EVENT_BREGEN, building_regen_event,
01031 BUILDING_REPAIR_DELAY, NULL);
01032 }
01033
01034 static void damage_cf(MECH * mech, mapobj * o, int from, int to, int damage)
01035 {
01036 int destroy = 0;
01037 int start_regen = 0;
01038
01039 if(from == to)
01040 start_regen = 1;
01041 damage = MIN(from, damage);
01042 if(from == damage)
01043 destroy = 1;
01044 from -= damage;
01045 set_building_cf(o->obj, from, to);
01046 if(destroy) {
01047 mech_printf(mech, MECHALL,
01048 "You hit %s for %d points of damage, destroying it!",
01049 structure_name(o), damage);
01050 notify_except(o->obj, NOTHING, o->obj,
01051 tprintf
01052 ("%s is hit for %d more points of damage, destroying it!",
01053 MyToUpper(structure_name(o)), damage));
01054 MechLOSBroadcast(mech, tprintf("hits %s, destroying it!",
01055 structure_name(o), damage));
01056 start_regen = 2;
01057 } else {
01058 mech_printf(mech, MECHALL,
01059 "You hit %s for %d points of damage.",
01060 structure_name(o), damage);
01061 notify_except(o->obj, NOTHING, o->obj,
01062 tprintf("%s is hit for %d points of damage.",
01063 MyToUpper(structure_name(o)), damage));
01064 }
01065 if(start_regen)
01066 possibly_start_building_regen(o->obj);
01067 }
01068
01069 void hit_building(MECH * mech, int x, int y, int weapindx, int damage)
01070 {
01071 mapobj *o;
01072 MAP *map;
01073 MAP *nmap;
01074 int loop, num_missiles_hit, hit_roll;
01075 int i1, i2;
01076
01077 if(!(map = getMap(mech->mapindex)))
01078 return;
01079 if(!(o = find_entrance_by_xy(map, x, y)))
01080 return;
01081 if(!(nmap = getMap(o->obj)))
01082 return;
01083 if(!damage) {
01084 if(!IsMissile(weapindx))
01085 damage = MechWeapons[weapindx].damage;
01086 else {
01087
01088 for(loop = 0; MissileHitTable[loop].key != -1; loop++)
01089 if(MissileHitTable[loop].key == weapindx)
01090 break;
01091 if(!(MissileHitTable[loop].key == weapindx))
01092 return;
01093 if((MechWeapons[weapindx].type == STREAK) &&
01094 (!AngelECMDisturbed(mech)))
01095 num_missiles_hit = MissileHitTable[loop].num_missiles[10];
01096 else {
01097 hit_roll = Roll() - 2;
01098 num_missiles_hit =
01099 MissileHitTable[loop].num_missiles[hit_roll];
01100 }
01101 damage = num_missiles_hit * MechWeapons[weapindx].damage;
01102 }
01103 }
01104 if(!damage)
01105 return;
01106 if(MapIsCS(map) || BuildIsCS(nmap)) {
01107 mech_notify(mech, MECHALL, "Your shot only scratches the paint!");
01108 return;
01109 }
01110 if(!get_building_cf(o->obj, &i1, &i2))
01111 return;
01112 damage_cf(mech, o, i1, i2, damage);
01113 }
01114
01115 void fire_hex(MECH * mech, int x, int y, int meant)
01116 {
01117 MAP *map;
01118
01119 if(!(map = getMap(mech->mapindex)))
01120 return;
01121 switch (GetTerrain(map, x, y)) {
01122 case HEAVY_FOREST:
01123 break;
01124 case LIGHT_FOREST:
01125 break;
01126 default:
01127 return;
01128 }
01129 if(meant) {
01130 MechLOSBroadcast(mech, tprintf("'s shot ignites %d,%d!", x, y));
01131 mech_printf(mech, MECHALL, "You ignite %d,%d.", x, y);
01132 } else {
01133 MechLOSBroadcast(mech, tprintf("'s stray shot ignites %d,%d!", x, y));
01134 mech_printf(mech, MECHALL, "You accidentally ignite %d,%d!", x, y);
01135 }
01136 add_decoration(map, x, y, TYPE_FIRE, FIRE, FIRE_DURATION);
01137 }
01138
01139 void steppable_base_check(MECH * mech, int x, int y)
01140 {
01141 mapobj *o;
01142 MAP *map;
01143 MAP *nmap;
01144
01145 map = getMap(mech->mapindex);
01146 if(!map)
01147 return;
01148 if(MechZ(mech) != Elevation(map, x, y))
01149 return;
01150 if(!(is_hangar_hex(map, x, y)))
01151 return;
01152 if(!(o = find_entrance_by_xy(map, x, y)))
01153 return;
01154 if(!(nmap = getMap(o->obj)))
01155 return;
01156 if(BuildIsInvis(nmap))
01157 return;
01158 if(BuildIsHidden(nmap) && !MadePerceptionRoll(mech, 0))
01159 return;
01160 mech_printf(mech, MECHALL, "%s has CF of %d.",
01161 MyToUpper(structure_name(o)), nmap->cf);
01162 }
01163
01164 void show_building_in_hex(MECH * mech, int x, int y)
01165 {
01166 mapobj *o;
01167 MAP *map;
01168 MAP *nmap;
01169
01170 if(!(map = getMap(mech->mapindex))) {
01171 mech_notify(mech, MECHALL,
01172 "The sensors detect no building in the hex!");
01173 return;
01174 }
01175 if(!(o = find_entrance_by_xy(map, x, y))) {
01176 mech_notify(mech, MECHALL,
01177 "The sensors detect no building in the hex!");
01178 return;
01179 }
01180 if(!(nmap = getMap(o->obj))) {
01181 mech_notify(mech, MECHALL,
01182 "The sensors detect no building in the hex!");
01183 return;
01184 }
01185 if(BuildIsInvis(nmap) || (BuildIsHidden(nmap) &&
01186 !MadePerceptionRoll(mech,
01187 (int) (FindRange
01188 (MechX(mech),
01189 MechY(mech),
01190 MechZ(mech), x, y,
01191 0) + 0.95)))) {
01192 mech_notify(mech, MECHALL,
01193 "The sensors detect no building in the hex!");
01194 return;
01195 }
01196 mech_printf(mech, MECHALL, "%s's CF is %d.",
01197 MyToUpper(structure_name(o)), nmap->cf);
01198 }
01199
01200 int obj_size(MAP * map)
01201 {
01202 int s = 0;
01203 mapobj *m;
01204 int i;
01205
01206 for(i = 0; i < NUM_MAPOBJTYPES; i++)
01207 if(map->mapobj[i])
01208 for(m = first_mapobj(map, i); m; m = next_mapobj(m))
01209 s += sizeof(mapobj);
01210 return s;
01211 }
01212
01213 int map_underlying_terrain(MAP * map, int x, int y)
01214 {
01215 char c;
01216
01217 if(!map)
01218 return 0;
01219 c = find_decorations(map, x, y);
01220 if(c)
01221 return c;
01222 return GetTerrain(map, x, y);
01223 }
01224
01225 int mech_underlying_terrain(MECH * mech)
01226 {
01227 char c;
01228 MAP *map = FindObjectsData(mech->mapindex);
01229
01230 if(!map)
01231 return MechTerrain(mech);
01232 c = find_decorations(map, MechX(mech), MechY(mech));
01233 if(c)
01234 return c;
01235 return MechTerrain(mech);
01236 }