src/hcode/btech/mechrep.c

Go to the documentation of this file.
00001 /*
00002  * Last modified: Thu Aug 13 23:41:12 1998 fingon
00003  * Copyright (c) 1999-2005 Kevin Stevens
00004  *   All right reserved
00005  */
00006 
00007 #include "config.h"
00008 
00009 #include <stdio.h>
00010 #include <stdlib.h>
00011 #include <math.h>
00012 #include <sys/file.h>
00013 #include <dirent.h>
00014 #include <sys/stat.h>
00015 
00016 #define MECH_STAT_C                             /* want to use the POSIX stat() call. */
00017 
00018 #include "externs.h"
00019 #include "mech.h"
00020 #include "mechrep.h"
00021 #include "create.h"
00022 #include "p.mech.build.h"
00023 #include "p.mech.status.h"
00024 #include "p.template.h"
00025 #include "p.mechrep.h"
00026 #include "p.mech.restrict.h"
00027 #include "p.mech.consistency.h"
00028 #include "p.mech.utils.h"
00029 #include "mech.events.h"
00030 
00031 /* Selectors */
00032 #define SPECIAL_FREE 0
00033 #define SPECIAL_ALLOC 1
00034 
00035 extern char *strtok(char *s, const char *ct);
00036 
00037 /* EXTERNS THAT SHOULDN'T BE IN HERE! */
00038 extern void *FindObjectsData(dbref key);
00039 dbref match_thing(dbref player, char *name);
00040 void muxevent_remove_data(void *data);
00041 
00042 #define MECHREP_COMMON(a) \
00043 struct mechrep_data *rep = (struct mechrep_data *) data; \
00044 MECH *mech; \
00045 DOCHECK(!Template(player), "I'm sorry Dave, can't do that."); \
00046 if (!CheckData(player, rep)) return; \
00047 if (a) { DOCHECK(rep->current_target == -1, "You must set a target first!"); \
00048 mech = getMech (rep->current_target); \
00049 if (!CheckData(player, mech)) return; }
00050 
00051 /*--------------------------------------------------------------------------*/
00052 
00053 /* Code Begins                                                              */
00054 
00055 /*--------------------------------------------------------------------------*/
00056 
00057 /* Alloc free function */
00058 
00059 /* Alloc/free routine */
00060 
00061 void newfreemechrep(dbref key, void **data, int selector)
00062 {
00063         struct mechrep_data *new = *data;
00064 
00065         switch (selector) {
00066         case SPECIAL_ALLOC:
00067                 new->current_target = -1;
00068                 break;
00069         }
00070 }
00071 
00072 /* With cap R means restricted command */
00073 
00074 void mechrep_Rresetcrits(dbref player, void *data, char *buffer)
00075 {
00076         int i;
00077 
00078         MECHREP_COMMON(1);
00079         notify(player, "Default criticals set!");
00080         for(i = 0; i < NUM_SECTIONS; i++)
00081                 FillDefaultCriticals(mech, i);
00082 }
00083 
00084 void mechrep_Rdisplaysection(dbref player, void *data, char *buffer)
00085 {
00086         char *args[1];
00087         int index;
00088 
00089         MECHREP_COMMON(1);
00090         DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
00091                         "You must specify a section to list the criticals for!");
00092         index = ArmorSectionFromString(MechType(mech), MechMove(mech), args[0]);
00093         DOCHECK(index == -1, "Invalid section!");
00094         CriticalStatus(player, mech, index);
00095 }
00096 
00097 #define MechComputersRadioRange(mech) \
00098 (DEFAULT_RADIORANGE * generic_radio_multiplier(mech))
00099 
00100 void mechrep_Rsetradio(dbref player, void *data, char *buffer)
00101 {
00102         char *args[2];
00103         int i;
00104 
00105         MECHREP_COMMON(1);
00106         switch (mech_parseattributes(buffer, args, 2)) {
00107         case 0:
00108                 notify(player,
00109                            "This remains to be done [showing of stuff when no args]");
00110                 return;
00111         case 2:
00112                 notify(player, "Too many args, unable to cope().");
00113                 return;
00114         }
00115         i = BOUNDED(1, atoi(args[0]), 5);
00116         notify_printf(player, "Radio level set to %d.", i);
00117         MechRadio(mech) = i;
00118         MechRadioType(mech) = generic_radio_type(MechRadio(mech), 0);
00119         notify_printf(player, "Number of freqs: %d  Extra stuff: %d",
00120                                   MechRadioType(mech) % 16, (MechRadioType(mech) / 16) * 16);
00121         MechRadioRange(mech) = MechComputersRadioRange(mech);
00122         notify_printf(player, "Radio range set to %d.",
00123                                   (int) MechRadioRange(mech));
00124 }
00125 
00126 void mechrep_Rsettarget(dbref player, void *data, char *buffer)
00127 {
00128         char *args[2];
00129         int newmech;
00130 
00131         MECHREP_COMMON(0);
00132         switch (mech_parseattributes(buffer, args, 2)) {
00133         case 1:
00134                 newmech = match_thing(player, args[0]);
00135                 DOCHECK(!(Good_obj(newmech) &&
00136                                   Hardcode(newmech)), "That is not a BattleMech or Vehicle!");
00137                 rep->current_target = newmech;
00138                 notify_printf(player, "Mech to repair changed to #%d", newmech);
00139                 break;
00140         default:
00141                 notify(player, "Too many arguments!");
00142         }
00143 }
00144 
00145 void mechrep_Rsettype(dbref player, void *data, char *buffer)
00146 {
00147         char *args[1];
00148 
00149         MECHREP_COMMON(1);
00150         DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
00151                         "Invalid number of arguments!");
00152         switch (toupper(args[0][0])) {
00153         case 'M':
00154                 MechType(mech) = CLASS_MECH;
00155                 MechMove(mech) = MOVE_BIPED;
00156                 notify(player, "Type set to MECH");
00157                 break;
00158         case 'Q':
00159                 MechType(mech) = CLASS_MECH;
00160                 MechMove(mech) = MOVE_QUAD;
00161                 notify(player, "Type set to QUAD");
00162                 break;
00163         case 'G':
00164                 MechType(mech) = CLASS_VEH_GROUND;
00165                 notify(player, "Type set to VEHICLE");
00166                 break;
00167         case 'V':
00168                 MechType(mech) = CLASS_VTOL;
00169                 MechMove(mech) = MOVE_VTOL;
00170                 notify(player, "Type set to VTOL");
00171                 break;
00172         case 'N':
00173                 MechType(mech) = CLASS_VEH_NAVAL;
00174                 notify(player, "Type set to NAVAL");
00175                 break;
00176         case 'A':
00177                 MechType(mech) = CLASS_AERO;
00178                 MechMove(mech) = MOVE_FLY;
00179                 notify(player, "Type set to AeroSpace");
00180                 break;
00181         case 'D':
00182                 MechType(mech) = CLASS_DS;
00183                 MechMove(mech) = MOVE_FLY;
00184                 notify(player, "Type set to DropShip");
00185                 break;
00186         case 'S':
00187                 MechType(mech) = CLASS_SPHEROID_DS;
00188                 MechMove(mech) = MOVE_FLY;
00189                 notify(player, "Type set to SpheroidDropship");
00190                 break;
00191         case 'B':
00192                 MechType(mech) = CLASS_BSUIT;
00193                 MechMove(mech) = MOVE_BIPED;
00194                 notify(player, "Type set to BattleSuit");
00195                 break;
00196         default:
00197                 notify(player,
00198                            "Types are: MECH, GROUND, VTOL, NAVAL, AERO, DROPSHIP and SPHEROIDDROPSHIP");
00199                 break;
00200         }
00201 }
00202 
00203 #define SETVALUE_FUNCTION_FLOAT(funcname,valname,valstring,modifier) \
00204 void funcname (dbref player, void *data, char *buffer) \
00205 { char *args[1]; float f; MECHREP_COMMON(1); \
00206   DOCHECK(mech_parseattributes (buffer, args, 1) != 1, \
00207           tprintf("Invalid number of arguments to Set%s!", valstring)); \
00208   f = atof(args[0]); \
00209   valname = f * modifier; \
00210   notify(player, tprintf("%s changed to %.2f.", valstring, valname)); \
00211 }
00212 
00213 #define SETVALUE_FUNCTION_INT(funcname,valname,valstring,modifier) \
00214 void funcname (dbref player, void *data, char *buffer) \
00215 { char *args[1]; int f; MECHREP_COMMON(1); \
00216   DOCHECK(mech_parseattributes (buffer, args, 1) != 1, \
00217           tprintf("Invalid number of arguments to Set%s!", valstring)); \
00218   f = atoi(args[0]); \
00219   valname = f * modifier; \
00220   notify(player, tprintf("%s changed to %d.", valstring, valname)); \
00221 }
00222 
00223 SETVALUE_FUNCTION_FLOAT(mechrep_Rsetspeed, MechMaxSpeed(mech), "Maxspeed",
00224                                                 KPH_PER_MP);
00225 SETVALUE_FUNCTION_FLOAT(mechrep_Rsetjumpspeed, MechJumpSpeed(mech),
00226                                                 "Jumpspeed", KPH_PER_MP);
00227 SETVALUE_FUNCTION_INT(mechrep_Rsetheatsinks, MechRealNumsinks(mech),
00228                                           "Heatsinks", 1);
00229 SETVALUE_FUNCTION_INT(mechrep_Rsetlrsrange, MechLRSRange(mech), "LRSrange",
00230                                           1);
00231 SETVALUE_FUNCTION_INT(mechrep_Rsettacrange, MechTacRange(mech), "TACrange",
00232                                           1);
00233 SETVALUE_FUNCTION_INT(mechrep_Rsetscanrange, MechScanRange(mech),
00234                                           "SCANrange", 1);
00235 SETVALUE_FUNCTION_INT(mechrep_Rsetradiorange, MechRadioRange(mech),
00236                                           "RADIOrange", 1);
00237 SETVALUE_FUNCTION_INT(mechrep_Rsettons, MechTons(mech), "Tons", 1);
00238 
00239 void mechrep_Rsetmove(dbref player, void *data, char *buffer)
00240 {
00241         char *args[1];
00242 
00243         MECHREP_COMMON(1);
00244         DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
00245                         "Invalid number of arguments!");
00246         switch (toupper(args[0][0])) {
00247         case 'T':
00248                 MechMove(mech) = MOVE_TRACK;
00249                 notify(player, "Movement set to TRACKED");
00250                 break;
00251         case 'W':
00252                 MechMove(mech) = MOVE_WHEEL;
00253                 notify(player, "Movement set to WHEELED");
00254                 break;
00255         case 'H':
00256                 switch (toupper(args[0][1])) {
00257                 case 'O':
00258                         MechMove(mech) = MOVE_HOVER;
00259                         notify(player, "Movement set to HOVER");
00260                         break;
00261                 case 'U':
00262                         MechMove(mech) = MOVE_HULL;
00263                         notify(player, "Movement set to HULL");
00264                         break;
00265                 }
00266                 break;
00267         case 'V':
00268                 MechMove(mech) = MOVE_VTOL;
00269                 notify(player, "Movement set to VTOL");
00270                 break;
00271         case 'Q':
00272                 MechMove(mech) = MOVE_QUAD;
00273                 notify(player, "Movement set to QUAD");
00274                 break;
00275         case 'B':
00276                 MechMove(mech) = MOVE_BIPED;
00277                 notify(player, "Movement set to BIPED");
00278                 break;
00279         case 'S':
00280                 MechMove(mech) = MOVE_SUB;
00281                 notify(player, "Movement set to SUB");
00282                 break;
00283         case 'F':
00284                 switch (toupper(args[0][1])) {
00285                 case 'O':
00286                         MechMove(mech) = MOVE_FOIL;
00287                         notify(player, "Movement set to FOIL");
00288                         break;
00289                 case 'L':
00290                         MechMove(mech) = MOVE_FLY;
00291                         notify(player, "Movement set to FLY");
00292                         break;
00293                 }
00294         case 'N':
00295                 MechMove(mech) = MOVE_NONE;
00296                 notify(player, "Movement set to NONE");
00297                 break;
00298         default:
00299                 notify(player,
00300                            "Types are: TRACK, WHEEL, VTOL, QUAD, BIPED, HOVER, HULL, FLY, SUB, FOIL and NONE");
00301                 break;
00302         }
00303 }
00304 
00305 /*
00306  * Implement a name cache of a template names.  This allows differences
00307  * in case and characters past the 14th to be ignored in mech references
00308  * when loading templates.  Templates can also be stored in any subdirectory
00309  * of the main template directory instead of in just one of list of hard
00310  * coded subdirectories.  
00311  * 
00312  * CACHE_MAXNAME sets the limit on how long a template filename can be.
00313  * Any template with a filename longer than this is ignored and not stored
00314  * in the cache.
00315  *
00316  * MECH_MAXREF sets the number of signficant characters in a mechref when
00317  * searching the cache.  This should be equal to the length of the
00318  * 'mech_type' (minus one for the terminating '\0' character) field of
00319  * MECH structure.
00320  * 
00321  */
00322 
00323 enum {
00324         CACHE_MAXNAME = 24,
00325         MECH_MAXREF = 14
00326 };
00327 
00328 struct tmpldirent {
00329         char name[CACHE_MAXNAME + 1];
00330         char const *dir;
00331 };
00332 
00333 struct tmpldir {
00334         char name[CACHE_MAXNAME + 1];
00335         struct tmpldir *next;
00336 };
00337 
00338 struct tmpldirent *tmpl_list = NULL;
00339 int tmpl_pos = 0;
00340 int tmpl_len = 0;
00341 
00342 struct tmpldir *tmpldir_list = NULL;
00343 
00344 /*
00345  * The ordering function for the template name cache.  Used to sort and
00346  * search the cache.
00347  */
00348 static int tmplcmp(void const *v1, void const *v2)
00349 {
00350         struct tmpldirent const *p1 = v1;
00351         struct tmpldirent const *p2 = v2;
00352 
00353         return strncasecmp(p1->name, p2->name, MECH_MAXREF);
00354 }
00355 
00356 /*
00357  * Add all the template names in a directory to the template cache.
00358  */
00359 static int scan_template_dir(char const *dirname, char const *parent)
00360 {
00361         char buf[1000];
00362         int dirnamelen = strlen(dirname);
00363         DIR *dir = opendir(dirname);
00364 
00365         if(dir == NULL) {
00366                 return -1;
00367         }
00368 
00369         while (1) {
00370                 struct stat sb;
00371                 struct dirent *ent = readdir(dir);
00372 
00373                 if(ent == NULL) {
00374                         break;
00375                 }
00376 
00377                 if(dirnamelen + 1 + strlen(ent->d_name) + 1 > sizeof buf) {
00378                         continue;
00379                 }
00380 
00381                 sprintf(buf, "%s/%s", dirname, ent->d_name);
00382                 if(stat(buf, &sb) == -1) {
00383                         continue;
00384                 }
00385 
00386                 if(parent == NULL && S_ISDIR(sb.st_mode)
00387                    && ent->d_name[0] != '.' && strlen(ent->d_name) <= CACHE_MAXNAME) {
00388                         struct tmpldir *link;
00389 
00390                         Create(link, struct tmpldir, 1);
00391 
00392                         strcpy(link->name, ent->d_name);
00393                         link->next = tmpldir_list;
00394                         tmpldir_list = link;
00395                         continue;
00396                 }
00397 
00398                 if(!S_ISREG(sb.st_mode)) {
00399                         continue;
00400                 }
00401 
00402                 if(tmpl_pos == tmpl_len) {
00403                         if(tmpl_len == 0) {
00404                                 tmpl_len = 4;
00405                                 Create(tmpl_list, struct tmpldirent, tmpl_len);
00406                         } else {
00407                                 tmpl_len *= 2;
00408                                 ReCreate(tmpl_list, struct tmpldirent, tmpl_len);
00409                         }
00410                 }
00411 
00412                 strncpy(tmpl_list[tmpl_pos].name, ent->d_name, CACHE_MAXNAME);
00413                 tmpl_list[tmpl_pos].name[CACHE_MAXNAME] = '\0';
00414                 tmpl_list[tmpl_pos].dir = parent;
00415                 tmpl_pos++;
00416         }
00417 
00418         closedir(dir);
00419         return 0;
00420 }
00421 
00422 /*
00423  * Scan all the template names in the mech template directory.  Only looks
00424  * in the mech template directory and it immediate subdirectories. 
00425  * It doesn't recursively look any further down the tree.
00426  */
00427 
00428 static int scan_templates(char const *dir)
00429 {
00430         char buf[1000];
00431         struct tmpldir *p;
00432 
00433         if(scan_template_dir(dir, NULL) == -1) {
00434                 return -1;
00435         }
00436 
00437         p = tmpldir_list;
00438         while (p != NULL) {
00439                 sprintf(buf, "%s/%s", dir, p->name);
00440                 scan_template_dir(buf, p->name);
00441                 p = p->next;
00442         }
00443 
00444         qsort(tmpl_list, tmpl_pos, sizeof tmpl_list[0], tmplcmp);
00445 
00446         return 0;
00447 }
00448 
00449 /*
00450  * Free all the memory used by the template cache.  Sets the cache to
00451  * the empty state.
00452  */
00453 static void free_template_list()
00454 {
00455         struct tmpldir *p;
00456 
00457         free(tmpl_list);
00458 
00459         p = tmpldir_list;
00460         while (p != NULL) {
00461                 struct tmpldir *np = p->next;
00462 
00463                 free(p);
00464                 p = np;
00465         }
00466 
00467         tmpl_list = NULL;
00468         tmpldir_list = NULL;
00469         tmpl_pos = 0;
00470         tmpl_len = 0;
00471 
00472         return;
00473 }
00474 
00475 char *subdirs[] = {
00476         "3025",
00477         "3050",
00478         "3055",
00479         "3058",
00480         "3060",
00481         "2750",
00482         "Aero",
00483         "MISC",
00484         "Clan",
00485         "ClanVehicles",
00486         "Clan2nd",
00487         "ClanAero",
00488         "Custom",
00489         "Solaris",
00490         "Vehicles",
00491         "MFNA",
00492         "Infantry",
00493         NULL
00494 };
00495 
00496 void mechrep_Rloadnew(dbref player, void *data, char *buffer)
00497 {
00498         char *args[1];
00499 
00500         MECHREP_COMMON(1);
00501         if(mech_parseattributes(buffer, args, 1) == 1)
00502                 if(mech_loadnew(player, mech, args[0]) == 1) {
00503                         muxevent_remove_data((void *) mech);
00504                         clear_mech_from_LOS(mech);
00505                         notify(player, "Template loaded.");
00506                         return;
00507                 }
00508         notify(player, "Unable to read that template.");
00509 }
00510 
00511 void clear_mech(MECH * mech, int flag)
00512 {
00513         int i, j;
00514 
00515         mech->brief = 1;
00516 
00517         bzero(&mech->rd, sizeof(mech_rd));
00518         bzero(&mech->ud, sizeof(mech_ud));
00519 
00520         MechSpotter(mech) = -1;
00521         MechTarget(mech) = -1;
00522         MechChargeTarget(mech) = -1;
00523         MechChargeTimer(mech) = 0;
00524         MechChargeDistance(mech) = 0;
00525         MechSwarmTarget(mech) = -1;
00526         MechSwarmer(mech) = -1;
00527         MechDFATarget(mech) = -1;
00528         MechTargX(mech) = -1;
00529         MechStatus(mech) = 0;
00530         MechTargY(mech) = -1;
00531         MechPilot(mech) = -1;
00532         MechAim(mech) = NUM_SECTIONS;
00533         StopBurning(mech);
00534         if(flag) {
00535                 for(i = 0; i < NUM_TICS; i++)
00536                         for(j = 0; j < TICLONGS; j++)
00537                                 mech->tic[i][j] = 0;
00538                 for(i = 0; i < FREQS; i++) {
00539                         mech->freq[i] = 0;
00540                         mech->freqmodes[i] = 0;
00541                         mech->chantitle[i][0] = 0;
00542                 }
00543         }
00544 }
00545 
00546 char *mechref_path(char *id)
00547 {
00548         static char openfile[1024];
00549         FILE *fp;
00550         int i = 0;                                      /* this int has double use... ugly, but effective */
00551 
00552         /*
00553          * If the template name doesn't have slash search for it in the
00554          * template name cache.
00555          */
00556   redo:
00557         if(strchr(id, '/') == NULL && (tmpl_list != NULL ||
00558                                                                    scan_templates(MECH_PATH) != -1)) {
00559                 struct tmpldirent *ent;
00560                 struct tmpldirent key;
00561 
00562                 strncpy(key.name, id, CACHE_MAXNAME);
00563                 key.name[CACHE_MAXNAME] = '\0';
00564 
00565                 ent =
00566                         bsearch(&key, tmpl_list, tmpl_pos, sizeof tmpl_list[0], tmplcmp);
00567                 if(ent == NULL) {
00568                         return NULL;
00569                 }
00570                 if(ent->dir == NULL) {
00571                         sprintf(openfile, "%s/%s", MECH_PATH, ent->name);
00572                 } else {
00573                         sprintf(openfile, "%s/%s/%s", MECH_PATH, ent->dir, ent->name);
00574                 }
00575                 if(access(openfile, R_OK) != 0) {
00576                         /* The file is missing (or unreadable)
00577                            invalidate the cache and try again,
00578                            if *that* fails, fall back to the old version. */
00579                         if(!i) {
00580                                 i = 1;
00581                                 free_template_list();
00582                                 goto redo;
00583                         } else
00584                                 goto oldstyle;
00585                 }
00586                 return openfile;
00587         }
00588   oldstyle:
00589         /*
00590          * Look up a template name the old way...
00591          */
00592         sprintf(openfile, "%s/%s", MECH_PATH, id);
00593         fp = fopen(openfile, "r");
00594         for(i = 0; !fp && subdirs[i]; i++) {
00595                 sprintf(openfile, "%s/%s/%s", MECH_PATH, subdirs[i], id);
00596                 fp = fopen(openfile, "r");
00597         }
00598         if(fp) {
00599                 fclose(fp);
00600                 return openfile;
00601         }
00602         return NULL;
00603 }
00604 
00605 int load_mechdata2(dbref player, MECH * mech, char *id)
00606 {
00607         FILE *fp = NULL;
00608         char *filename;
00609 
00610         filename = mechref_path(id);
00611 
00612         if(!filename)
00613                 return 0;
00614         if(!(fp = fopen(filename, "r")))
00615                 return 0;
00616         fclose(fp);
00617         return load_template(player, mech, filename) >= 0 ? 1 : 0;
00618 }
00619 
00620 extern int num_def_weapons;
00621 
00622 int unable_to_find_proper_type(int i)
00623 {
00624         if(!i)
00625                 return 0;
00626         if(IsWeapon(i)) {
00627                 if(i > (num_def_weapons))
00628                         return 1;
00629         }
00630         if(IsAmmo(i)) {
00631                 if((Ammo2Weapon(i) + 1) > (num_def_weapons))
00632                         return 1;
00633         }
00634         if(IsSpecial(i))
00635                 if(Special2I(i) >= count_special_items())
00636                         return 1;
00637         return 0;
00638 }
00639 
00640 int load_mechdata(MECH * mech, char *id)
00641 {
00642         FILE *fp = NULL;
00643         int i, j, k, t;
00644         int i1, i2, i3, i4, i5, i6;
00645         char *filename;
00646 
00647         filename = mechref_path(id);
00648         TEMPLATE_GERR(filename == NULL, tprintf("No matching file for '%s'.",
00649                                                                                         id));
00650         if(filename)
00651                 fp = fopen(filename, "r");
00652         TEMPLATE_GERR(!fp, tprintf("Unable to open file %s (%s)!", filename, id));
00653         strncpy(MechType_Ref(mech), id, 15);
00654         MechType_Ref(mech)[14] = '\0';
00655         TEMPLATE_GERR(fscanf(fp, "%d %d %d %d %d %f %f %d\n", &i1, &i2, &i3,
00656                                                  &i4, &i5, &MechMaxSpeed(mech), &MechJumpSpeed(mech),
00657                                                  &i6) < 8,
00658                                   "Old template loading system: %s is invalid template file.",
00659                                   id);
00660         MechTons(mech) = i1;
00661         MechTacRange(mech) = i2;
00662         MechLRSRange(mech) = i3;
00663         MechScanRange(mech) = i4;
00664         MechRealNumsinks(mech) = i5;
00665 #define DROP(a) \
00666   if (i6 & a) i6 &= ~a
00667         DROP(32768);                            /* Quad */
00668         DROP(16384);                            /* Salvagetech */
00669         DROP(8192);                                     /* Cargotech */
00670         DROP(4196);                                     /* Watergun */
00671         MechSpecials(mech) = i6;
00672         for(k = 0; k < NUM_SECTIONS; k++) {
00673                 i = k;
00674                 if(MechType(mech) == 4) {
00675                         switch (k) {
00676                         case 3:
00677                                 i = 4;
00678                                 break;
00679                         case 4:
00680                                 i = 5;
00681                                 break;
00682                         case 5:
00683                                 i = 3;
00684                                 break;
00685                         }
00686                 }
00687                 TEMPLATE_GERR(fscanf(fp, "%d %d %d %d\n", &i1, &i2, &i3, &i4) < 4,
00688                                           "Insufficient data reading section %d!", i);
00689                 MechSections(mech)[i].recycle = 0;
00690                 SetSectArmor(mech, i, i1);
00691                 SetSectOArmor(mech, i, i1);
00692                 SetSectInt(mech, i, i2);
00693                 SetSectOInt(mech, i, i2);
00694                 SetSectRArmor(mech, i, i3);
00695                 SetSectORArmor(mech, i, i3);
00696                 /* Remove all rampant AXEs from the arms themselves, we do
00697                    things differently here */
00698                 if(i4 & 4)
00699                         i4 &= ~4;
00700                 MechSections(mech)[i].config = i4;
00701                 for(j = 0; j < NUM_CRITICALS; j++) {
00702                         TEMPLATE_GERR(fscanf(fp, "%d %d %d\n", &i1, &i2, &i3) < 3,
00703                                                   "Insufficient data reading critical %d/%d!", i, j);
00704                         MechSections(mech)[i].criticals[j].type = i1;
00705                         TEMPLATE_GERR(unable_to_find_proper_type(GetPartType(mech, i,
00706                                                                                                                                  j)),
00707                                                   "Invalid datatype at %d/%d!", i, j);
00708                         if(IsSpecial(i1))
00709                                 i1 += SPECIAL_BASE_INDEX - OSPECIAL_BASE_INDEX;
00710                         if(IsWeapon(GetPartType(mech, i, j)) &&
00711                            IsAMS((t = Weapon2I(GetPartType(mech, i, j))))) {
00712                                 if(MechWeapons[t].special & CLAT)
00713                                         MechSpecials(mech) |= CL_ANTI_MISSILE_TECH;
00714                                 else
00715                                         MechSpecials(mech) |= IS_ANTI_MISSILE_TECH;
00716                         }
00717                         MechSections(mech)[i].criticals[j].data = i2;
00718                         MechSections(mech)[i].criticals[j].firemode = i3;
00719                 }
00720         }
00721         if(fscanf(fp, "%d %d\n", &i1, &i2) == 2) {
00722                 MechType(mech) = i1;
00723                 TEMPLATE_GERR(MechType(mech) > CLASS_LAST, "Invalid 'mech type!");
00724                 MechMove(mech) = i2;
00725                 TEMPLATE_GERR(MechMove(mech) > MOVENEMENT_LAST,
00726                                           "Invalid movenement type!");
00727         }
00728         if(fscanf(fp, "%d\n", &i1) != 1)
00729                 MechRadioRange(mech) = DEFAULT_RADIORANGE;
00730         else
00731                 MechRadioRange(mech) = i1;
00732         fclose(fp);
00733         return 1;
00734 }
00735 
00736 #undef  LOADNEW_LOADS_OLD_IF_FAIL
00737 #define LOADNEW_LOADS_MUSE_FORMAT
00738 
00739 int mech_loadnew(dbref player, MECH * mech, char *id)
00740 {
00741         char mech_origid[100];
00742 
00743         strncpy(mech_origid, MechType_Ref(mech), 99);
00744         mech_origid[99] = '\0';
00745 
00746         if(!strcmp(mech_origid, id)) {
00747                 clear_mech(mech, 0);
00748                 if(load_mechdata2(player, mech, id) <= 0)
00749                         return load_mechdata(mech, id) > 0;
00750                 return 1;
00751         } else {
00752                 clear_mech(mech, 1);
00753                 if(load_mechdata2(player, mech, id) < 1)
00754 #ifdef LOADNEW_LOADS_MUSE_FORMAT
00755                         if(load_mechdata(mech, id) < 1)
00756 #endif
00757 #ifdef LOADNEW_LOADS_OLD_IF_FAIL
00758                                 if(load_mechdata2(player, mech, mech_origid) < 1)
00759 #ifdef LOADNEW_LOADS_MUSE_FORMAT
00760                                         if(load_mechdata(mech, mech_origid) < 1)
00761 #endif
00762 #endif
00763                                                 return 0;
00764         }
00765         return 1;
00766 }
00767 
00768 void mechrep_Rrestore(dbref player, void *data, char *buffer)
00769 {
00770         char *c;
00771 
00772         MECHREP_COMMON(1);
00773         c = silly_atr_get(mech->mynum, A_MECHREF);
00774         DOCHECK(!c || !*c, "Sorry, I don't know what type of mech this is");
00775         DOCHECK(mech_loadnew(player, mech, c) == 1, "Restoration complete!");
00776         notify(player, "Unable to restore this mech!.");
00777 }
00778 
00779 void mechrep_Rsavetemp(dbref player, void *data, char *buffer)
00780 {
00781         char *args[1];
00782         FILE *fp;
00783         char openfile[512];
00784         int i, j;
00785 
00786         MECHREP_COMMON(1);
00787 
00788         free_template_list();
00789 
00790         DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
00791                         "You must specify a template name!");
00792         DOCHECK(strstr(args[0], "/"), "Invalid file name!");
00793         notify_printf(player, "Saving %s...", args[0]);
00794         sprintf(openfile, "%s/", MECH_PATH);
00795         strcat(openfile, args[0]);
00796         DOCHECK(!(fp =
00797                           fopen(openfile, "w")),
00798                         "Unable to open/create mech file! Sorry.");
00799         fprintf(fp, "%d %d %d %d %d %.2f %.2f %d\n", MechTons(mech),
00800                         MechTacRange(mech), MechLRSRange(mech), MechScanRange(mech),
00801                         MechRealNumsinks(mech), MechMaxSpeed(mech), MechJumpSpeed(mech),
00802                         MechSpecials(mech));
00803         for(i = 0; i < NUM_SECTIONS; i++) {
00804                 fprintf(fp, "%d %d %d %d\n", GetSectArmor(mech, i),
00805                                 GetSectInt(mech, i), GetSectRArmor(mech, i),
00806                                 MechSections(mech)[i].config);
00807                 for(j = 0; j < NUM_CRITICALS; j++) {
00808                         fprintf(fp, "%d %d %d\n",
00809                                         MechSections(mech)[i].criticals[j].type,
00810                                         MechSections(mech)[i].criticals[j].data,
00811                                         MechSections(mech)[i].criticals[j].firemode);
00812                 }
00813         }
00814         fprintf(fp, "%d %d\n", MechType(mech), MechMove(mech));
00815         fprintf(fp, "%d\n", MechRadioRange(mech));
00816         fclose(fp);
00817         notify(player, "Saving complete!");
00818 }
00819 
00820 /*
00821  * Template saving routines and logic.
00822  */
00823 void mechrep_Rsavetemp2(dbref player, void *data, char *buffer)
00824 {
00825         char *args[1];
00826         char openfile[512];
00827 
00828         MECHREP_COMMON(1);
00829 
00830         free_template_list();
00831 
00832         // No template name given.
00833         if(mech_parseattributes(buffer, args, 1) != 1) {
00834             notify(player, "You must specify a template name!");
00835             return;
00836         }
00837         
00838         // Anti-twink measure. Don't allow directory saving... yet
00839         if(strstr(args[0], "/")) { 
00840             notify(player, "Invalid file name!");
00841             return;
00842         }
00843             
00844         notify_printf(player, "Saving %s", args[0]);
00845         sprintf(openfile, "%s/", MECH_PATH);
00846         strcat(openfile, args[0]);
00847         
00848         // Just warn on overweight.
00849         if(mech_weight_sub(GOD, mech, -1) > (MechTons(mech) * 1024))
00850             notify(player, "Warning: Template Overweight, see @weight.");
00851         
00852         // I/O or Permissions error.
00853         if(save_template(player, mech, args[0], openfile) < 0) {
00854             notify(player, "Error saving the template file!");
00855             return ;
00856         }
00857 
00858         notify(player, "Saving complete!");
00859 } // end mechrep_Rsavetemp2
00860 
00861 /*
00862  * Emits the valid sections when a player tries to setarmor/addsp/reload an
00863  * invalid section
00864  */
00865 void invalid_section(dbref player, MECH * mech)
00866 {
00867         int mechtype = MechType(mech);
00868         int movetype = MechMove(mech);
00869         
00870         notify(player, "Not a legal armor location, must be one of:");
00871         
00872         switch(mechtype) {
00873                 case CLASS_MW:
00874                 case CLASS_MECH:
00875                         notify(player, "HEAD (H), CTORSO (CT), LTORSO (LT), RTORSO (RT)");
00876                         
00877                         if (movetype == MOVE_QUAD)
00878                                 notify(player, "LARM (LA), RARM (RA), LLEG (LL), RLEG (RL)");
00879                         else
00880                                 notify(player, "FLLEG (FLL), FRLEG (FRL), RLLEG (RLL), RRLEG (RRL)");
00881                         
00882                         break;
00883                 case CLASS_VEH_NAVAL:
00884                 case CLASS_VEH_GROUND:
00885                         notify(player, "FSIDE (FS), RSIDE (RS), LSIDE (LS), ASIDE (AS), TURRET (TU)");
00886                         break;
00887                 case CLASS_VTOL:
00888                         notify(player, "FSIDE (FS), RSIDE (RS), LSIDE (LS), ASIDE (AS), ROTOR (RO)");
00889                         break;
00890                 case CLASS_AERO:
00891                         notify(player, "NOSE (N), LWING (LW), RWING (RW), ASIDE (AS)");
00892                         break;
00893                 case CLASS_DS:
00894                         notify(player, "NOSE (N), LWING (LW), RWING (RW), LRWING (LR), RRWING (RR), ASIDE (AS)");
00895                         break;
00896                 case CLASS_SPHEROID_DS:
00897                         notify(player, "NOSE (N), FRSIDE (FR), FLSIDE (FL), RLSIDE (RL), RRSIDE (RR), ASIDE (AS)");
00898                         break;
00899                 case CLASS_BSUIT:
00900                         notify(player, "S1, S2, S3, S4, S5, S6, S7, S8");
00901                         break;
00902                 default:
00903                         notify(player, "Invalid or unknown unit type!");
00904         }
00905 }
00906 
00907 /*
00908  * Logic for the 'setarmor' mechrep command.
00909  */
00910 void mechrep_Rsetarmor(dbref player, void *data, char *buffer)
00911 {
00912         char *args[4];
00913         int argc;
00914         int index;
00915         int temp;
00916 
00917         MECHREP_COMMON(1);
00918         argc = mech_parseattributes(buffer, args, 4);
00919         DOCHECK(!argc, "Invalid number of arguments!");
00920         index = ArmorSectionFromString(MechType(mech), MechMove(mech), args[0]);
00921         
00922         if(index == -1) {
00923                 // Invalid section, emit error and valid choices for unit type.
00924                 invalid_section(player, mech);
00925                 return;
00926         }
00927         
00928         argc--;
00929         
00930         if(argc) {
00931                 // One Argument Given.
00932                 temp = atoi(args[1]);
00933                 if(temp < 0)
00934                         notify(player, "Invalid armor value!");
00935                 else {
00936                         notify_printf(player, "Front armor set to    : %d", temp);
00937                         SetSectArmor(mech, index, temp);
00938                         SetSectOArmor(mech, index, temp);
00939                 }
00940                 argc--;
00941         }
00942         if(argc) {
00943                 // Two Arguments Given.
00944                 temp = atoi(args[2]);
00945                 if(temp < 0)
00946                         notify(player, "Invalid Internal armor value!");
00947                 else {
00948                         notify_printf(player, "Internal armor set to : %d", temp);
00949                         SetSectInt(mech, index, temp);
00950                         SetSectOInt(mech, index, temp);
00951                 }
00952                 argc--;
00953         }
00954         if(argc) {
00955                 // Three Arguments Given.
00956                 temp = atoi(args[3]);
00957                 if(index == CTORSO || index == RTORSO || index == LTORSO) {
00958                         if(temp < 0)
00959                                 notify(player, "Invalid Rear armor value!");
00960                         else {
00961                                 notify_printf(player, "Rear armor set to     : %d", temp);
00962                                 SetSectRArmor(mech, index, temp);
00963                                 SetSectORArmor(mech, index, temp);
00964                         }
00965                 } else
00966                         notify(player, "Only the torso can have rear armor.");
00967         }
00968 }
00969 
00970 /* 
00971  * Handles the adding of weapons via the 'addweap' command in the form of:
00972  * addweap <weap> <loc> <crits> [<flags>]
00973  * Current Flags: O = OS, T = TC, R = Rear
00974  */
00975 void mechrep_Raddweap(dbref player, void *data, char *buffer)
00976 {
00977         char *args[20];                         /* The argument array */
00978         int argc;                               /* Count of arguments */
00979         int index;                              /* Used to determine section validity */
00980         int weapindex;                          /* Weapon index number */
00981         int weapnumcrits;                       /* Number of crits the desired weapon occupies. */
00982         int weaptype;                           /* The weapon type */
00983         int loop, temp;                         /* Loop Counters */
00984         int isrear = 0;                         /* Rear mounted? */
00985         int istc = 0;                           /* Is the weap TC'd? */
00986         int isoneshot = 0;                      /* If 1, weapon is a One-Shot (OS) Weap */
00987         int isrocket = 0;                       /* Is this a rocket launcher? */
00988         int argstoiter;                         /* Holder for figuring out how many args to scan */
00989         char flagholder;                        /* Holder for flag comparisons */
00990 
00991         MECHREP_COMMON(1);
00992 
00993         argc = mech_parseattributes(buffer, args, 20);
00994         DOCHECK(argc < 3, "Invalid number of arguments!")
00995 
00996         index = ArmorSectionFromString(MechType(mech), MechMove(mech), args[1]);
00997         
00998         if(index == -1) {
00999                 // Invalid section entered. Emit error and valid sections.
01000                 invalid_section(player, mech);
01001                 return;
01002         }
01003 
01004         weapindex = WeaponIndexFromString(args[0]);
01005 
01006         if(weapindex == -1) {
01007                 notify_printf(player, "That is not a valid weapon!");
01008                 DumpWeapons(player);
01009                 return;
01010         }
01011 
01012         /* 
01013          * There are always 3 arguments that preceed flags. 
01014          * addweap <weap> <loc> <crit>, 0, 1, and 2 respectively in args[][]. 
01015          * By subtracting 3, we figure out how many of our arguments are actually 
01016          * flags.
01017          */
01018         argstoiter = argc - 3;
01019 
01020         /*
01021          * Now we take those additional flags and look for matches. argc is 
01022          * decremented to keep track of how many of our arguments are crit
01023          * locations.
01024          */
01025         for(loop = 0; loop < argstoiter; loop++) {
01026                 flagholder = toupper(args[3 + loop][0]);
01027 
01028                 if(flagholder == 'T') {
01029                         /* Targeting Computer */
01030                         istc = 1;
01031                 } else if(flagholder == 'R') {
01032                         /* Rear Mounted */
01033                         isrear = 1;
01034                 } else if(flagholder == 'O') {
01035                         /* One-Shot */
01036                         isoneshot = 1;
01037                 }
01038 
01039                 /* 
01040                  * If it's a letter, it's not a crit location. If a
01041                  * player throws numbers in with the crit flags, then
01042                  * they'll see error messages about crit counts. Need
01043                  * to find a better way to fool-proof this.
01044                  */
01045                 if(isalpha(flagholder))
01046                         argc--;
01047 
01048         }                                                       /* end for */
01049 
01050         /* Chop off the first the first two redundant args. */
01051         argc -= 2;
01052 
01053         weapnumcrits = GetWeaponCrits(mech, weapindex);
01054 
01055         /* Check to see if player gives enough crits and start adding if so. */
01056         if(argc < weapnumcrits) {
01057                 notify_printf(player,
01058                                           "Not enough critical slots specified! (Given: %i, Needed: %i)",
01059                                           argc, weapnumcrits);
01060         } else if(argc > weapnumcrits) {
01061                 notify_printf(player,
01062                                           "Too many critical slots specified! (Given: %i, Needed: %i)",
01063                                           argc, weapnumcrits);
01064         } else {
01065                 for(loop = 0; loop < GetWeaponCrits(mech, weapindex); loop++) {
01066                         temp = atoi(args[2 + loop]);
01067                         temp--;                         /* From 1 based to 0 based */
01068                         DOCHECK(temp < 0 ||
01069                                         temp > NUM_CRITICALS, "Bad critical location!");
01070                         MechSections(mech)[index].criticals[temp].type =
01071                                 (I2Weapon(weapindex));
01072                         MechSections(mech)[index].criticals[temp].firemode = 0;
01073                         MechSections(mech)[index].criticals[temp].ammomode = 0;
01074 
01075                         /* If this is a Rocket Launcher, use isrocket to set the OS flag */
01076                         if(MechWeapons[weapindex].special & ROCKET)
01077                                 isrocket = 1;
01078 
01079                         if(isrear)
01080                                 MechSections(mech)[index].criticals[temp].firemode |=
01081                                         REAR_MOUNT;
01082 
01083                         if(istc)
01084                                 MechSections(mech)[index].criticals[temp].firemode |= ON_TC;
01085 
01086                         /* Rockets are OS too */
01087                         if(isoneshot || isrocket)
01088                                 MechSections(mech)[index].criticals[temp].firemode |= OS_MODE;
01089                 }
01090                 if(IsAMS(weapindex)) {
01091                         if(MechWeapons[weapindex].special & CLAT)
01092                                 MechSpecials(mech) |= CL_ANTI_MISSILE_TECH;
01093                         else
01094                                 MechSpecials(mech) |= IS_ANTI_MISSILE_TECH;
01095                 }
01096                 notify_printf(player, "Weapon added.");
01097         }
01098 }                                                               /* end mechrep_Raddweap() */
01099 
01100 void mechrep_Rfiremode(dbref player, void *data, char *buffer)
01101 {
01102         char *args[4];
01103         int argc;
01104         int section, critical, weaptype;
01105 
01106         MECHREP_COMMON(1);
01107         argc = mech_parseattributes(buffer, args, 2);
01108         DOCHECK(argc <2, "MECHREP: Invalid Syntax. Try FireMode <Weapon#> <Mode>");
01109 
01110         weaptype = FindWeaponNumberOnMech_Advanced(mech, atoi(args[0]), &section, &critical, 0);
01111 
01112         if(MechWeapons[weaptype].ammoperton == 0) {
01113                                 notify(player, "That weapon doesn't require ammo!");
01114                                 return;
01115         }
01116         
01117         if(MechSections(mech)[section].criticals[critical].firemode & OS_MODE) {
01118                 notify(player,"Keeping One Shot Mode!");
01119                 MechSections(mech)[section].criticals[critical].ammomode = 0;
01120         }
01121         else
01122            if(!(MechSections(mech)[section].criticals[critical].firemode & HALFTON_MODE)) {
01123           
01124                         MechSections(mech)[section].criticals[critical].firemode = 0;
01125                         MechSections(mech)[section].criticals[critical].ammomode = 0;
01126         }
01127 
01128 
01129 
01130 
01131         switch (toupper(args[1][0])) {
01132                         case 'W':
01133                                 MechSections(mech)[section].criticals[critical].ammomode |=
01134                                         SWARM_MODE;
01135                                 break;
01136                         case '1':
01137                                 MechSections(mech)[section].criticals[critical].ammomode |=
01138                                         SWARM1_MODE;
01139                                 break;
01140                         case 'I':
01141                                 MechSections(mech)[section].criticals[critical].ammomode |=
01142                                         INFERNO_MODE;
01143                                 break;
01144                         case 'L':
01145                                 MechSections(mech)[section].criticals[critical].ammomode |=
01146                                         LBX_MODE;
01147                                 break;
01148                         case 'A':
01149                                 MechSections(mech)[section].criticals[critical].ammomode |=
01150                                         ARTEMIS_MODE;
01151                                 break;
01152                         case 'N':
01153                                 MechSections(mech)[section].criticals[critical].ammomode |=
01154                                         NARC_MODE;
01155                                 break;
01156                         case 'C':
01157                                 MechSections(mech)[section].criticals[critical].ammomode |=
01158                                         CLUSTER_MODE;
01159                                 break;
01160                         case 'M':
01161                                 MechSections(mech)[section].criticals[critical].ammomode |=
01162                                         MINE_MODE;
01163                                 break;
01164                         case 'S':
01165                                 MechSections(mech)[section].criticals[critical].ammomode |=
01166                                         SMOKE_MODE;
01167                                 break;
01168                         case 'X':
01169                                 MechSections(mech)[section].criticals[critical].ammomode |=
01170                                         INARC_EXPLO_MODE;
01171                                 break;
01172                         case 'Y':
01173                                 MechSections(mech)[section].criticals[critical].ammomode |=
01174                                         INARC_HAYWIRE_MODE;
01175                                 break;
01176                         case 'E':
01177                                 MechSections(mech)[section].criticals[critical].ammomode |=
01178                                         INARC_ECM_MODE;
01179                                 break;
01180                         case 'R':
01181                                 MechSections(mech)[section].criticals[critical].ammomode |=
01182                                         AC_AP_MODE;
01183                                 break;
01184                         case 'F':
01185                                 MechSections(mech)[section].criticals[critical].ammomode |=
01186                                         AC_FLECHETTE_MODE;
01187                                 break;
01188                         case 'D':
01189                                 MechSections(mech)[section].criticals[critical].ammomode |=
01190                                         AC_INCENDIARY_MODE;
01191                                 break;
01192                         case 'P':
01193                                 MechSections(mech)[section].criticals[critical].ammomode |=
01194                                         AC_PRECISION_MODE;
01195                                 break;
01196                         case 'T':
01197                                 MechSections(mech)[section].criticals[critical].ammomode |=
01198                                         STINGER_MODE;
01199                                 break;
01200                         case 'U':
01201                                 MechSections(mech)[section].criticals[critical].ammomode |=
01202                                         AC_CASELESS_MODE;
01203                                 break;
01204                         case 'J':
01205                                 MechSections(mech)[section].criticals[critical].firemode |= WILL_JETTISON_MODE;
01206                                 break;
01207                         case 'G':
01208                                 MechSections(mech)[section].criticals[critical].ammomode |=
01209                                         SGUIDED_MODE;
01210                                 break;
01211                         case '-':
01212                                 MechSections(mech)[section].criticals[critical].ammomode = 0;
01213                                 MechSections(mech)[section].criticals[critical].firemode = 0;
01214                         }
01215 
01216                 notify(player,"Firemode changed!");                                     
01217 
01218 }
01219 /*
01220  * Logic for the 'reload' mechrep command.
01221  */
01222 void mechrep_Rreload(dbref player, void *data, char *buffer)
01223 {
01224         char *args[4];
01225         int argc;
01226         int index;
01227         int weapindex;
01228         int subsect;
01229 
01230         MECHREP_COMMON(1);
01231         argc = mech_parseattributes(buffer, args, 4);
01232         DOCHECK(argc <= 2, "Invalid number of arguments!");
01233         weapindex = WeaponIndexFromString(args[0]);
01234         
01235         if(weapindex == -1) {
01236                 notify(player, "That is not a valid weapon!");
01237                 DumpWeapons(player);
01238                 return;
01239         }
01240         
01241         index = ArmorSectionFromString(MechType(mech), MechMove(mech), args[1]);
01242         
01243         if(index == -1) {
01244                 // Invalid section entered. Emit error and valid sections.
01245                 invalid_section(player, mech);
01246                 return;
01247         }
01248         
01249         subsect = atoi(args[2]);
01250         subsect--;                                      /* from 1 based to 0 based */
01251         DOCHECK(subsect < 0 ||
01252                         subsect >= CritsInLoc(mech, index), "Critslot out of range!");
01253         if(MechWeapons[weapindex].ammoperton == 0)
01254                 notify(player, "That weapon doesn't require ammo!");
01255         else {
01256                 MechSections(mech)[index].criticals[subsect].type = I2Ammo(weapindex);
01257                 if(!(MechSections(mech)[index].criticals[subsect].firemode & HALFTON_MODE)) {
01258                         MechSections(mech)[index].criticals[subsect].firemode = 0;
01259                         MechSections(mech)[index].criticals[subsect].ammomode = 0;
01260                 }
01261 
01262                 if(argc > 3)
01263                         switch (toupper(args[3][0])) {
01264                         case '+':
01265                                 MechSections(mech)[index].criticals[subsect].firemode |=
01266                                         HALFTON_MODE;
01267                                 break;
01268                         case 'W':
01269                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01270                                         SWARM_MODE;
01271                                 break;
01272                         case '1':
01273                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01274                                         SWARM1_MODE;
01275                                 break;
01276                         case 'I':
01277                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01278                                         INFERNO_MODE;
01279                                 break;
01280                         case 'L':
01281                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01282                                         LBX_MODE;
01283                                 break;
01284                         case 'A':
01285                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01286                                         ARTEMIS_MODE;
01287                                 break;
01288                         case 'N':
01289                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01290                                         NARC_MODE;
01291                                 break;
01292                         case 'C':
01293                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01294                                         CLUSTER_MODE;
01295                                 break;
01296                         case 'M':
01297                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01298                                         MINE_MODE;
01299                                 break;
01300                         case 'S':
01301                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01302                                         SMOKE_MODE;
01303                                 break;
01304                         case 'X':
01305                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01306                                         INARC_EXPLO_MODE;
01307                                 break;
01308                         case 'Y':
01309                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01310                                         INARC_HAYWIRE_MODE;
01311                                 break;
01312                         case 'E':
01313                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01314                                         INARC_ECM_MODE;
01315                                 break;
01316                         case 'R':
01317                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01318                                         AC_AP_MODE;
01319                                 break;
01320                         case 'F':
01321                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01322                                         AC_FLECHETTE_MODE;
01323                                 break;
01324                         case 'D':
01325                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01326                                         AC_INCENDIARY_MODE;
01327                                 break;
01328                         case 'P':
01329                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01330                                         AC_PRECISION_MODE;
01331                                 break;
01332                         case 'T':
01333                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01334                                         STINGER_MODE;
01335                                 break;
01336                         case 'U':
01337                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01338                                         AC_CASELESS_MODE;
01339                                 break;
01340                         case 'G':
01341                                 MechSections(mech)[index].criticals[subsect].ammomode |=
01342                                         SGUIDED_MODE;
01343                                 break;
01344                         case '-':
01345                                 MechSections(mech)[index].criticals[subsect].ammomode = 0;
01346                                 MechSections(mech)[index].criticals[subsect].firemode = 0;
01347                         }
01348 
01349                 MechSections(mech)[index].criticals[subsect].data =
01350                         FullAmmo(mech, index, subsect);
01351                 notify(player, "Weapon loaded!");
01352         }
01353 }
01354 
01355 /*
01356  * Logic for the 'repair' mechrep command.
01357  */
01358 void mechrep_Rrepair(dbref player, void *data, char *buffer)
01359 {
01360         char *args[4];
01361         int argc;
01362         int index;
01363         int temp;
01364 
01365         MECHREP_COMMON(1);
01366         argc = mech_parseattributes(buffer, args, 4);
01367         DOCHECK(argc <= 2, "Invalid number of arguments!");
01368         index = ArmorSectionFromString(MechType(mech), MechMove(mech), args[0]);
01369         
01370         if(index == -1) {
01371                 // Invalid section entered. Emit error and valid sections.
01372                 invalid_section(player, mech);
01373                 return;
01374         }
01375         
01376         temp = atoi(args[2]);
01377         DOCHECK(temp < 0, "Illegal value for armor!");
01378         
01379         switch (args[1][0]) {
01380         case 'A':
01381         case 'a':
01382                 /* armor */
01383                 SetSectArmor(mech, index, temp);
01384                 notify(player, "Armor repaired!");
01385                 break;
01386         case 'I':
01387         case 'i':
01388                 /* internal */
01389                 SetSectInt(mech, index, temp);
01390                 notify(player, "Internal structure repaired!");
01391                 break;
01392         case 'C':
01393         case 'c':
01394                 /* criticals */
01395                 temp--;
01396                 if(temp >= 0 && temp < NUM_CRITICALS) {
01397                         MechSections(mech)[index].criticals[temp].data = 0;
01398                         notify(player, "Critical location repaired!");
01399                 } else {
01400                         notify(player, "Critical Location out of range!");
01401                 }
01402                 break;
01403         case 'R':
01404         case 'r':
01405                 /* rear */
01406                 if(index == CTORSO || index == LTORSO || index == RTORSO) {
01407                         SetSectRArmor(mech, index, temp);
01408                         notify(player, "Rear armor repaired!");
01409                 } else {
01410                         notify(player,
01411                                    "Only the center, rear and left torso have rear armor!");
01412                 }
01413                 break;
01414         default:
01415                 notify(player, "Illegal Type-> must be ARMOR, INTERNAL, CRIT, REAR");
01416                 return;
01417         }
01418 }
01419 
01420 /*
01421    ADDSP <ITEM> <LOCATION> <SUBSECT> [<DATA>]
01422  */
01423 void mechrep_Raddspecial(dbref player, void *data, char *buffer)
01424 {
01425         char *args[4];
01426         int argc;
01427         int index;
01428         int itemcode;
01429         int subsect;
01430         int newdata;
01431         int max;
01432 
01433         MECHREP_COMMON(1);
01434         argc = mech_parseattributes(buffer, args, 4);
01435         DOCHECK(argc <= 2, "Invalid number of arguments!");
01436         itemcode = FindSpecialItemCodeFromString(args[0]);
01437         
01438         if(itemcode == -1)
01439                 if(strcasecmp(args[0], "empty")) {
01440                         notify(player, "That is not a valid special object!");
01441                         DumpMechSpecialObjects(player);
01442                         return;
01443                 }
01444         index = ArmorSectionFromString(MechType(mech), MechMove(mech), args[1]);
01445         
01446         if(index == -1) {
01447                 // Invalid section entered. Emit error and valid sections.
01448                 invalid_section(player, mech);
01449                 return;
01450         }
01451         subsect = atoi(args[2]);
01452         subsect--;
01453         max = CritsInLoc(mech, index);
01454         DOCHECK(subsect < 0 || subsect >= max, "Critslot out of range!");
01455         if(argc == 4)
01456                 newdata = atoi(args[3]);
01457         else
01458                 newdata = 0;
01459         MechSections(mech)[index].criticals[subsect].type =
01460                 itemcode < 0 ? 0 : I2Special(itemcode);
01461         MechSections(mech)[index].criticals[subsect].data = newdata;
01462         switch (itemcode) {
01463         case CASE:
01464                 MechSections(mech)[(MechType(mech) ==
01465                                                         CLASS_VEH_GROUND) ? BSIDE : index].config |=
01466                         CASE_TECH;
01467                 notify(player, "CASE Technology added to section.");
01468                 break;
01469         case TRIPLE_STRENGTH_MYOMER:
01470                 MechSpecials(mech) |= TRIPLE_MYOMER_TECH;
01471                 notify(player, "Triple Strength Myomer Technology added to 'Mech.");
01472                 break;
01473         case MASC:
01474                 MechSpecials(mech) |= MASC_TECH;
01475                 notify(player, "Myomer Accelerator Signal Circuitry added to 'Mech.");
01476                 break;
01477         case C3_MASTER:
01478                 MechSpecials(mech) |= C3_MASTER_TECH;
01479                 notify(player, "C3 Command Unit added to 'Mech.");
01480                 break;
01481         case C3_SLAVE:
01482                 MechSpecials(mech) |= C3_SLAVE_TECH;
01483                 notify(player, "C3 Slave Unit added to 'Mech.");
01484                 break;
01485         case ARTEMIS_IV:
01486                 MechSections(mech)[index].criticals[subsect].data--;
01487                 MechSpecials(mech) |= ARTEMIS_IV_TECH;
01488                 notify(player, "Artemis IV Fire-Control System added to 'Mech.");
01489                 notify_printf(player,
01490                                           "System will control the weapon which starts at slot %d.",
01491                                           newdata);
01492                 break;
01493         case ECM:
01494                 MechSpecials(mech) |= ECM_TECH;
01495                 notify(player, "Guardian ECM Suite added to 'Mech.");
01496                 break;
01497         case ANGELECM:
01498                 MechSpecials2(mech) |= ANGEL_ECM_TECH;
01499                 notify(player, "Angel ECM Suite added to 'Mech.");
01500                 break;
01501         case BEAGLE_PROBE:
01502                 MechSpecials(mech) |= BEAGLE_PROBE_TECH;
01503                 notify(player, "Beagle Active Probe added to 'Mech.");
01504                 break;
01505         case TAG:
01506                 MechSpecials2(mech) |= TAG_TECH;
01507                 notify(player, "TAG added to 'Mech.");
01508                 break;
01509         case C3I:
01510                 MechSpecials2(mech) |= C3I_TECH;
01511                 notify(player, "Improved C3 added to 'Mech.");
01512                 break;
01513         case BLOODHOUND_PROBE:
01514                 MechSpecials2(mech) |= BLOODHOUND_PROBE_TECH;
01515                 notify(player, "Bloodhound Active Probe added to 'Mech.");
01516                 break;
01517         case TARGETING_COMPUTER:
01518                 MechSpecials2(mech) |= TCOMP_TECH;
01519                 notify(player, "Targeting Computer added to 'Mech.");
01520                 break;
01521         }
01522         notify(player, "Critical slot filled.");
01523 }
01524 
01525 extern char *specials[];
01526 extern char *specials2[];
01527 extern char *infantry_specials[];
01528 
01529 char *techstatus_func(MECH * mech)
01530 {
01531         return (MechSpecials(mech) ||
01532                         MechSpecials2(mech)) ? BuildBitStringwdelim2(specials, specials2,
01533                                                                                                    MechSpecials(mech),
01534                                                                                                    MechSpecials2(mech)) : "";
01535 }
01536 
01537 void mechrep_Rshowtech(dbref player, void *data, char *buffer)
01538 {
01539         int i;
01540         char *techstring;
01541         char location[20];
01542 
01543         MECHREP_COMMON(1);
01544         notify(player, "--------Advanced Technology--------");
01545         if(MechSpecials(mech) & TRIPLE_MYOMER_TECH)
01546                 notify(player, "Triple Strength Myomer");
01547         if(MechSpecials(mech) & MASC_TECH)
01548                 notify(player, "Myomer Accelerator Signal Circuitry");
01549         for(i = 0; i < NUM_SECTIONS; i++)
01550                 if(MechSections(mech)[i].config & CASE_TECH) {
01551                         ArmorStringFromIndex(i, location, MechType(mech), MechMove(mech));
01552                         notify_printf(player,
01553                                                   "Cellular Ammunition Storage Equipment in %s",
01554                                                   location);
01555                 }
01556         if(MechSpecials(mech) & CLAN_TECH) {
01557                 notify(player, "Mech is set to Clan Tech.  This means:");
01558                 notify(player, "    Mech automatically has Double Heat Sink Tech");
01559                 notify(player, "    Mech automatically has CASE in all sections");
01560         }
01561         if(MechSpecials(mech) & DOUBLE_HEAT_TECH)
01562                 notify(player, "Mech uses Double Heat Sinks");
01563         if(MechSpecials(mech) & CL_ANTI_MISSILE_TECH)
01564                 notify(player, "Clan style Anti-Missile System");
01565         if(MechSpecials(mech) & IS_ANTI_MISSILE_TECH)
01566                 notify(player, "Inner Sphere style Anti-Missile System");
01567         if(MechSpecials(mech) & FLIPABLE_ARMS)
01568                 notify(player, "The arms may be flipped into the rear firing arc");
01569         if(MechSpecials(mech) & C3_MASTER_TECH)
01570                 notify(player, "C3 Command Computer");
01571         if(MechSpecials(mech) & C3_SLAVE_TECH)
01572                 notify(player, "C3 Slave Computer");
01573         if(MechSpecials(mech) & ARTEMIS_IV_TECH)
01574                 notify(player, "Artemis IV Fire-Control System");
01575         if(MechSpecials(mech) & ECM_TECH)
01576                 notify(player, "Guardian ECM Suite");
01577         if(MechSpecials2(mech) & ANGEL_ECM_TECH)
01578                 notify(player, "Angel ECM Suite");
01579         if(MechSpecials(mech) & BEAGLE_PROBE_TECH)
01580                 notify(player, "Beagle Active Probe");
01581         if(MechSpecials2(mech) & TAG_TECH)
01582                 notify(player, "Target Aquisition Gear");
01583         if(MechSpecials2(mech) & C3I_TECH)
01584                 notify(player, "Improved C3");
01585         if(MechSpecials2(mech) & BLOODHOUND_PROBE_TECH)
01586                 notify(player, "Bloodhound Active Probe");
01587         if(MechSpecials(mech) & ICE_TECH)
01588                 notify(player, "It has ICE engine");
01589 
01590         /* Infantry related stuff */
01591         if(MechInfantrySpecials(mech) & INF_SWARM_TECH)
01592                 notify(player, "Can swarm enemy units");
01593         if(MechInfantrySpecials(mech) & INF_MOUNT_TECH)
01594                 notify(player, "Can mount friendly units");
01595         if(MechInfantrySpecials(mech) & INF_ANTILEG_TECH)
01596                 notify(player, "Can do anti-leg attacks");
01597         if(MechInfantrySpecials(mech) & CS_PURIFIER_STEALTH_TECH)
01598                 notify(player, "Has CS Purifier Stealth");
01599         if(MechInfantrySpecials(mech) & DC_KAGE_STEALTH_TECH)
01600                 notify(player, "Has DC Kage Stealth");
01601         if(MechInfantrySpecials(mech) & FWL_ACHILEUS_STEALTH_TECH)
01602                 notify(player, "Has FWL Achileus Stealth");
01603         if(MechInfantrySpecials(mech) & FC_INFILTRATOR_STEALTH_TECH)
01604                 notify(player, "Has FC Infiltrator Stealth");
01605         if(MechInfantrySpecials(mech) & FC_INFILTRATORII_STEALTH_TECH)
01606                 notify(player, "Has FC InfiltratorII Stealth");
01607         if(MechInfantrySpecials(mech) & MUST_JETTISON_TECH)
01608                 notify(player,
01609                            "Must jettison backpack before jumping/using specials");
01610         if(MechInfantrySpecials(mech) & CAN_JETTISON_TECH)
01611                 notify(player, "Can jettison backpack");
01612 
01613         notify(player, "Brief version (May have something previous hadn't):");
01614         techstring = mechrep_gettechstring(mech);
01615         if(techstring && techstring[0])
01616                 notify(player, techstring);
01617         else
01618                 notify(player, "-");
01619 }
01620 
01621 char *mechrep_gettechstring(MECH * mech)
01622 {
01623         return BuildBitString3(specials, specials2, infantry_specials,
01624                                                    MechSpecials(mech), MechSpecials2(mech),
01625                                                    MechInfantrySpecials(mech));
01626 }
01627 
01628 void mechrep_Rdeltech(dbref player, void *data, char *buffer)
01629 {
01630         int i, j;
01631         int Type;
01632         int nv, nv2;
01633 
01634         MECHREP_COMMON(1);
01635         /* Compare what the user gave to our specials lists */
01636         nv = BuildBitVector(specials, buffer);
01637         nv2 = BuildBitVector(specials2, buffer);
01638 
01639         /* Make sure what they gave was valid */
01640         if(((nv < 0) && (nv2 < 0)) && (strcasecmp(buffer, "all") != 0) &&
01641            (strcasecmp(buffer, "Case") != 0)) {
01642                 notify(player, "Invalid tech: Available techs:");
01643                 notify(player, "\tAll");
01644                 notify(player, "\tCase");
01645 
01646                 for(nv = 0; specials[nv]; nv++)
01647                         notify_printf(player, "\t%s", specials[nv]);
01648 
01649                 for(nv = 0; specials2[nv]; nv++)
01650                         notify_printf(player, "\t%s", specials2[nv]);
01651 
01652                 return;
01653         }
01654 
01655         /* Check to see if user specified anything */
01656         if(((!nv) && (!nv2)) && (strcasecmp(buffer, "all") != 0) &&
01657            (strcasecmp(buffer, "Case") != 0)) {
01658                 notify(player, "Nothing specified");
01659                 return;
01660         }
01661 
01662         /* Check to see if user specified 'ALL' */
01663         if(strcasecmp(buffer, "all") == 0) {
01664 
01665                 for(i = 0; i < NUM_SECTIONS; i++) {
01666 
01667                         if((MechSections(mech)[i].config & CASE_TECH)
01668                            || (MechSpecials(mech) & TRIPLE_MYOMER_TECH)
01669                            || (MechSpecials(mech) & MASC_TECH)) {
01670 
01671                                 for(j = 0; j < NUM_CRITICALS; j++) {
01672                                         Type = MechSections(mech)[i].criticals[j].type;
01673 
01674                                         if(Type == I2Special((CASE))
01675                                            || Type == I2Special((TRIPLE_STRENGTH_MYOMER))
01676                                            || Type == I2Special((MASC))) {
01677                                                 MechSections(mech)[i].criticals[j].type = EMPTY;
01678                                         }
01679                                 }
01680                                 MechSections(mech)[i].config &= ~CASE_TECH;
01681 
01682                         }
01683                 }
01684 
01685                 MechSpecials(mech) = 0;
01686                 MechSpecials2(mech) = 0;
01687                 notify(player, "All Advanced Technology Removed");
01688                 return;
01689         }
01690 
01691         if(strcasecmp(buffer, "Case") == 0) {
01692                 for(i = 0; i < NUM_SECTIONS; i++) {
01693                         if(MechSections(mech)[i].config & CASE_TECH) {
01694                                 for(j = 0; j < NUM_CRITICALS; j++) {
01695                                         Type = MechSections(mech)[i].criticals[j].type;
01696 
01697                                         if(Type == I2Special((CASE))) {
01698                                                 MechSections(mech)[i].criticals[j].type = EMPTY;
01699                                         }
01700                                 }
01701                                 MechSections(mech)[i].config &= ~CASE_TECH;
01702                         }
01703                 }
01704                 notify(player, "Case Technology Removed");
01705                 return;
01706         }
01707 
01708         if(nv > 0) {
01709 
01710                 if(strcasecmp(buffer, "TripleMyomerTech") == 0) {
01711                         if(MechSpecials(mech) & TRIPLE_MYOMER_TECH) {
01712                                 for(i = 0; i < NUM_SECTIONS; i++) {
01713                                         for(j = 0; j < NUM_CRITICALS; j++) {
01714                                                 Type = MechSections(mech)[i].criticals[j].type;
01715 
01716                                                 if(Type == I2Special((TRIPLE_STRENGTH_MYOMER))) {
01717                                                         MechSections(mech)[i].criticals[j].type = EMPTY;
01718                                                 }
01719                                         }
01720                                 }
01721                         }
01722                 } else if(strcasecmp(buffer, "Masc") == 0) {
01723                         if(MechSpecials(mech) & MASC_TECH) {
01724                                 for(i = 0; i < NUM_SECTIONS; i++) {
01725                                         for(j = 0; j < NUM_CRITICALS; j++) {
01726                                                 Type = MechSections(mech)[i].criticals[j].type;
01727 
01728                                                 if(Type == I2Special((MASC))) {
01729                                                         MechSections(mech)[i].criticals[j].type = EMPTY;
01730                                                 }
01731                                         }
01732                                 }
01733                         }
01734                 }
01735 
01736                 MechSpecials(mech) &= ~nv;
01737                 notify_printf(player, "%s Technology Removed", buffer);
01738 
01739         } else {
01740 
01741                 MechSpecials2(mech) &= ~nv2;
01742                 notify_printf(player, "%s Technology Removed", buffer);
01743 
01744         }
01745         return;
01746 }
01747 
01748 void mechrep_Raddtech(dbref player, void *data, char *buffer)
01749 {
01750         int nv, nv2;
01751 
01752         MECHREP_COMMON(1);
01753         nv = BuildBitVector(specials, buffer);
01754         nv2 = BuildBitVector(specials2, buffer);
01755 
01756         if((nv < 0) && (nv2 < 0)) {
01757                 notify(player, "Invalid tech: Available techs:");
01758 
01759                 for(nv = 0; specials[nv]; nv++)
01760                         notify_printf(player, "\t%s", specials[nv]);
01761 
01762                 for(nv = 0; specials2[nv]; nv++)
01763                         notify_printf(player, "\t%s", specials2[nv]);
01764 
01765                 return;
01766         }
01767 
01768         if((!nv) && (!nv2)) {
01769                 notify(player, "Nothing set!");
01770                 return;
01771         }
01772 
01773         if(nv > 0) {
01774                 MechSpecials(mech) |= nv;
01775                 notify_printf(player, "Set: %s", BuildBitString(specials, nv));
01776         } else {
01777                 MechSpecials2(mech) |= nv2;
01778                 notify_printf(player, "Set: %s", BuildBitString(specials2, nv2));
01779         }
01780 
01781 }
01782 
01783 void mechrep_Rdelinftech(dbref player, void *data, char *buffer)
01784 {
01785         MECH *mech = (MECH *) data;
01786 
01787         MechInfantrySpecials(mech) = 0;
01788         notify(player, "Advanced Infantry Technology Deleted");
01789 }
01790 
01791 void mechrep_Raddinftech(dbref player, void *data, char *buffer)
01792 {
01793         int nv;
01794 
01795         MECHREP_COMMON(1);
01796         nv = BuildBitVector(infantry_specials, buffer);
01797 
01798         if(MechType(mech) != CLASS_BSUIT) {
01799                 notify(player, "That is not a valid target for infantry technologies. Try a Suit!");
01800                 return;
01801         }
01802 
01803         if(nv < 0) {
01804                 notify(player, "Invalid infantry tech: Available techs:");
01805 
01806                 for(nv = 0; infantry_specials[nv]; nv++)
01807                         notify_printf(player, "\t%s", infantry_specials[nv]);
01808                 return;
01809         }
01810 
01811         if(!nv) {
01812                 notify(player, "Nothing set!");
01813                 return;
01814         }
01815 
01816         if(nv > 0) {
01817                 MechInfantrySpecials(mech) |= nv;
01818                 notify_printf(player, "Set: %s", BuildBitString(infantry_specials,
01819                                                                                                                 nv));
01820         }
01821 
01822 }
01823 
01824 void mechrep_setcargospace(dbref player, void *data, char *buffer)
01825 {
01826         char *args[2];
01827         int argc;
01828         int cargo;
01829         int max;
01830 
01831         MECHREP_COMMON(1);
01832         argc = mech_parseattributes(buffer, args, 2);
01833         DOCHECK(argc != 2, "Invalid number of arguements!");
01834 
01835         cargo = (atoi(args[0]) * 50);
01836         DOCHECK(cargo < 0 || cargo > 100000, "Doesn't that seem excessive?");
01837         CargoSpace(mech) = cargo;
01838 
01839         max = (atoi(args[1]));
01840         max = (BOUNDED(1, max, 100));
01841         CarMaxTon(mech) = (char) max;
01842 
01843         notify_printf(player, "%3.2f cargospace and %d tons of maxton space set.",
01844                                   (float) ((float) cargo / 100), (int) max);
01845 
01846 }
01847 
01848 MECH *load_refmech(char *reference)
01849 {
01850         static MECH cachemech;
01851         static char cacheref[1024];
01852 
01853         if(!strcmp(cacheref, reference))
01854                 return &cachemech;
01855         if(mech_loadnew(GOD, &cachemech, reference) < 1) {
01856                 cacheref[0] = '\0';
01857                 return NULL;
01858         }
01859         strncpy(cacheref, reference, 1023);
01860         cacheref[1023] = '\0';
01861         return &cachemech;
01862 }

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