src/hcode/btech/map.obj.c

Go to the documentation of this file.
00001 /*
00002  * Author: Markus Stenberg <fingon@iki.fi>
00003  *
00004  *  Copyright (c) 1996 Markus Stenberg
00005  *  Copyright (c) 1998-2002 Thomas Wouters
00006  *  Copyright (c) 2000-2002 Cord Awtry
00007  *       All rights reserved
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         /* Delete the specified mapobj */
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         /* Then, the silly thing. Decorations, they suck */
00156         if(type <= TYPE_LAST_DEC) {
00157                 /* Need to alter terrain back to 'usual' */
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                 /* Cackle */
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                 /* Cackle */
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 /*   if (Number(1, 10) == 3) */
00469 
00470 /*     { */
00471 
00472 /*       x = o->x; */
00473 
00474 /*       y = o->y; */
00475 
00476 /*       fire_dissipation_event(e); */
00477 
00478 /*       add_decoration(map, x, y, TYPE_SMOKE, SMOKE, SMOKE_DURATION); */
00479 
00480 /*       return; */
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);                                     /* 2 hexes 'downwind' */
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         /* if (foo.datac) */
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         /* Clean out */
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         /* Entrance-checking code */
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 /* x y dist */
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];                    /* Build / Leave / Entrance */
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                 /* Update leave exit */
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                 /* Places you can enter this place from.. it's more or less
00920                    directly taken from BUILDENTRANCE */
00921                 tmps = silly_atr_get(loc, A_BUILDENTRANCE);
00922                 if(tmps) {
00923                         /* number number number number
00924                            or
00925                            x,y x,y x,y x,y
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                         /* Missile weapon.  Multiple Hit locations... */
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 }

Generated on Mon May 28 04:25:21 2007 for BattletechMUX by  doxygen 1.4.7