/*
* $Id: mechrep.c,v 1.5 2005/07/02 19:02:23 av1-op Exp $
*
* Last modified: Thu Aug 13 23:41:12 1998 fingon
* Copyright (c) 1999-2005 Kevin Stevens
* All right reserved
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/file.h>
#include <dirent.h>
#include <sys/stat.h>
#define MECH_STAT_C /* want to use the POSIX stat() call. */
#include "externs.h"
#include "mech.h"
#include "mechrep.h"
#include "create.h"
#include "p.mech.build.h"
#include "p.mech.status.h"
#include "p.template.h"
#include "p.mechrep.h"
#include "p.mech.restrict.h"
#include "p.mech.consistency.h"
#include "p.mech.utils.h"
#include "mech.events.h"
/* Selectors */
#define SPECIAL_FREE 0
#define SPECIAL_ALLOC 1
extern char *strtok(char *s, const char *ct);
/* EXTERNS THAT SHOULDN'T BE IN HERE! */
extern void *FindObjectsData(dbref key);
dbref match_thing(dbref player, char *name);
void muxevent_remove_data(void *data);
#define MECHREP_COMMON(a) \
struct mechrep_data *rep = (struct mechrep_data *) data; \
MECH *mech; \
DOCHECK(!Template(player), "I'm sorry Dave, can't do that."); \
if (!CheckData(player, rep)) return; \
if (a) { DOCHECK(rep->current_target == -1, "You must set a target first!"); \
mech = getMech (rep->current_target); \
if (!CheckData(player, mech)) return; }
/*--------------------------------------------------------------------------*/
/* Code Begins */
/*--------------------------------------------------------------------------*/
/* Alloc free function */
/* Alloc/free routine */
void newfreemechrep(dbref key, void **data, int selector)
{
struct mechrep_data *new = *data;
switch (selector) {
case SPECIAL_ALLOC:
new->current_target = -1;
break;
}
}
/* With cap R means restricted command */
void mechrep_Rresetcrits(dbref player, void *data, char *buffer)
{
int i;
MECHREP_COMMON(1);
notify(player, "Default criticals set!");
for (i = 0; i < NUM_SECTIONS; i++)
FillDefaultCriticals(mech, i);
}
void mechrep_Rdisplaysection(dbref player, void *data, char *buffer)
{
char *args[1];
int index;
MECHREP_COMMON(1);
DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
"You must specify a section to list the criticals for!");
index =
ArmorSectionFromString(MechType(mech), MechMove(mech), args[0]);
DOCHECK(index == -1, "Invalid section!");
CriticalStatus(player, mech, index);
}
#define MechComputersRadioRange(mech) \
(DEFAULT_RADIORANGE * generic_radio_multiplier(mech))
void mechrep_Rsetradio(dbref player, void *data, char *buffer)
{
char *args[2];
int i;
MECHREP_COMMON(1);
switch (mech_parseattributes(buffer, args, 2)) {
case 0:
notify(player,
"This remains to be done [showing of stuff when no args]");
return;
case 2:
notify(player, "Too many args, unable to cope().");
return;
}
i = BOUNDED(1, atoi(args[0]), 5);
notify(player, tprintf("Radio level set to %d.", i));
MechRadio(mech) = i;
MechRadioType(mech) = generic_radio_type(MechRadio(mech), 0);
notify(player, tprintf("Number of freqs: %d Extra stuff: %d",
MechRadioType(mech) % 16, (MechRadioType(mech) / 16) * 16));
MechRadioRange(mech) = MechComputersRadioRange(mech);
notify(player, tprintf("Radio range set to %d.",
(int) MechRadioRange(mech)));
}
void mechrep_Rsettarget(dbref player, void *data, char *buffer)
{
char *args[2];
int newmech;
MECHREP_COMMON(0);
switch (mech_parseattributes(buffer, args, 2)) {
case 1:
newmech = match_thing(player, args[0]);
DOCHECK(!(Good_obj(newmech) &&
Hardcode(newmech)),
"That is not a BattleMech or Vehicle!");
rep->current_target = newmech;
notify(player, tprintf("Mech to repair changed to #%d", newmech));
break;
default:
notify(player, "Too many arguments!");
}
}
void mechrep_Rsettype(dbref player, void *data, char *buffer)
{
char *args[1];
MECHREP_COMMON(1);
DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
"Invalid number of arguments!");
switch (toupper(args[0][0])) {
case 'M':
MechType(mech) = CLASS_MECH;
MechMove(mech) = MOVE_BIPED;
notify(player, "Type set to MECH");
break;
case 'Q':
MechType(mech) = CLASS_MECH;
MechMove(mech) = MOVE_QUAD;
notify(player, "Type set to QUAD");
break;
case 'G':
MechType(mech) = CLASS_VEH_GROUND;
notify(player, "Type set to VEHICLE");
break;
case 'V':
MechType(mech) = CLASS_VTOL;
MechMove(mech) = MOVE_VTOL;
notify(player, "Type set to VTOL");
break;
case 'N':
MechType(mech) = CLASS_VEH_NAVAL;
notify(player, "Type set to NAVAL");
break;
case 'A':
MechType(mech) = CLASS_AERO;
MechMove(mech) = MOVE_FLY;
notify(player, "Type set to AeroSpace");
break;
case 'D':
MechType(mech) = CLASS_DS;
MechMove(mech) = MOVE_FLY;
notify(player, "Type set to DropShip");
break;
case 'S':
MechType(mech) = CLASS_SPHEROID_DS;
MechMove(mech) = MOVE_FLY;
notify(player, "Type set to SpheroidDropship");
break;
case 'B':
MechType(mech) = CLASS_BSUIT;
MechMove(mech) = MOVE_BIPED;
notify(player, "Type set to BattleSuit");
break;
default:
notify(player,
"Types are: MECH, GROUND, VTOL, NAVAL, AERO, DROPSHIP and SPHEROIDDROPSHIP");
break;
}
}
#define SETVALUE_FUNCTION_FLOAT(funcname,valname,valstring,modifier) \
void funcname (dbref player, void *data, char *buffer) \
{ char *args[1]; float f; MECHREP_COMMON(1); \
DOCHECK(mech_parseattributes (buffer, args, 1) != 1, \
tprintf("Invalid number of arguments to Set%s!", valstring)); \
f = atof(args[0]); \
valname = f * modifier; \
notify(player, tprintf("%s changed to %.2f.", valstring, valname)); \
}
#define SETVALUE_FUNCTION_INT(funcname,valname,valstring,modifier) \
void funcname (dbref player, void *data, char *buffer) \
{ char *args[1]; int f; MECHREP_COMMON(1); \
DOCHECK(mech_parseattributes (buffer, args, 1) != 1, \
tprintf("Invalid number of arguments to Set%s!", valstring)); \
f = atoi(args[0]); \
valname = f * modifier; \
notify(player, tprintf("%s changed to %d.", valstring, valname)); \
}
SETVALUE_FUNCTION_FLOAT(mechrep_Rsetspeed, MechMaxSpeed(mech), "Maxspeed",
KPH_PER_MP);
SETVALUE_FUNCTION_FLOAT(mechrep_Rsetjumpspeed, MechJumpSpeed(mech),
"Jumpspeed", KPH_PER_MP);
SETVALUE_FUNCTION_INT(mechrep_Rsetheatsinks, MechRealNumsinks(mech),
"Heatsinks", 1);
SETVALUE_FUNCTION_INT(mechrep_Rsetlrsrange, MechLRSRange(mech), "LRSrange",
1);
SETVALUE_FUNCTION_INT(mechrep_Rsettacrange, MechTacRange(mech), "TACrange",
1);
SETVALUE_FUNCTION_INT(mechrep_Rsetscanrange, MechScanRange(mech),
"SCANrange", 1);
SETVALUE_FUNCTION_INT(mechrep_Rsetradiorange, MechRadioRange(mech),
"RADIOrange", 1);
SETVALUE_FUNCTION_INT(mechrep_Rsettons, MechTons(mech), "Tons", 1);
void mechrep_Rsetmove(dbref player, void *data, char *buffer)
{
char *args[1];
MECHREP_COMMON(1);
DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
"Invalid number of arguments!");
switch (toupper(args[0][0])) {
case 'T':
MechMove(mech) = MOVE_TRACK;
notify(player, "Movement set to TRACKED");
break;
case 'W':
MechMove(mech) = MOVE_WHEEL;
notify(player, "Movement set to WHEELED");
break;
case 'H':
switch (toupper(args[0][1])) {
case 'O':
MechMove(mech) = MOVE_HOVER;
notify(player, "Movement set to HOVER");
break;
case 'U':
MechMove(mech) = MOVE_HULL;
notify(player, "Movement set to HULL");
break;
}
break;
case 'V':
MechMove(mech) = MOVE_VTOL;
notify(player, "Movement set to VTOL");
break;
case 'Q':
MechMove(mech) = MOVE_QUAD;
notify(player, "Movement set to QUAD");
break;
case 'S':
MechMove(mech) = MOVE_SUB;
notify(player, "Movement set to SUB");
break;
case 'F':
switch (toupper(args[0][1])) {
case 'O':
MechMove(mech) = MOVE_FOIL;
notify(player, "Movement set to FOIL");
break;
case 'L':
MechMove(mech) = MOVE_FLY;
notify(player, "Movement set to FLY");
break;
}
case 'N':
MechMove(mech) = MOVE_NONE;
notify(player, "Movement set to NONE");
break;
default:
notify(player,
"Types are: TRACK, WHEEL, VTOL, HOVER, HULL, FLY, SUB, FOIL and NONE");
break;
}
}
/*
* Implement a name cache of a template names. This allows differences
* in case and characters past the 14th to be ignored in mech references
* when loading templates. Templates can also be stored in any subdirectory
* of the main template directory instead of in just one of list of hard
* coded subdirectories.
*
* CACHE_MAXNAME sets the limit on how long a template filename can be.
* Any template with a filename longer than this is ignored and not stored
* in the cache.
*
* MECH_MAXREF sets the number of signficant characters in a mechref when
* searching the cache. This should be equal to the length of the
* 'mech_type' (minus one for the terminating '\0' character) field of
* MECH structure.
*
*/
enum {
CACHE_MAXNAME = 24,
MECH_MAXREF = 14
};
struct tmpldirent {
char name[CACHE_MAXNAME + 1];
char const *dir;
};
struct tmpldir {
char name[CACHE_MAXNAME + 1];
struct tmpldir *next;
};
struct tmpldirent *tmpl_list = NULL;
int tmpl_pos = 0;
int tmpl_len = 0;
struct tmpldir *tmpldir_list = NULL;
/*
* The ordering function for the template name cache. Used to sort and
* search the cache.
*/
static int tmplcmp(void const *v1, void const *v2)
{
struct tmpldirent const *p1 = v1;
struct tmpldirent const *p2 = v2;
return strncasecmp(p1->name, p2->name, MECH_MAXREF);
}
/*
* Add all the template names in a directory to the template cache.
*/
static int scan_template_dir(char const *dirname, char const *parent)
{
char buf[1000];
int dirnamelen = strlen(dirname);
DIR *dir = opendir(dirname);
if (dir == NULL) {
return -1;
}
while (1) {
struct stat sb;
struct dirent *ent = readdir(dir);
if (ent == NULL) {
break;
}
if (dirnamelen + 1 + strlen(ent->d_name) + 1 > sizeof buf) {
continue;
}
sprintf(buf, "%s/%s", dirname, ent->d_name);
if (stat(buf, &sb) == -1) {
continue;
}
if (parent == NULL && S_ISDIR(sb.st_mode)
&& ent->d_name[0] != '.' &&
strlen(ent->d_name) <= CACHE_MAXNAME) {
struct tmpldir *link;
Create(link, struct tmpldir, 1);
strcpy(link->name, ent->d_name);
link->next = tmpldir_list;
tmpldir_list = link;
continue;
}
if (!S_ISREG(sb.st_mode)) {
continue;
}
if (tmpl_pos == tmpl_len) {
if (tmpl_len == 0) {
tmpl_len = 4;
Create(tmpl_list, struct tmpldirent, tmpl_len);
} else {
tmpl_len *= 2;
ReCreate(tmpl_list, struct tmpldirent, tmpl_len);
}
}
strncpy(tmpl_list[tmpl_pos].name, ent->d_name, CACHE_MAXNAME);
tmpl_list[tmpl_pos].name[CACHE_MAXNAME] = '\0';
tmpl_list[tmpl_pos].dir = parent;
tmpl_pos++;
}
closedir(dir);
return 0;
}
/*
* Scan all the template names in the mech template directory. Only looks
* in the mech template directory and it immediate subdirectories.
* It doesn't recursively look any further down the tree.
*/
static int scan_templates(char const *dir)
{
char buf[1000];
struct tmpldir *p;
if (scan_template_dir(dir, NULL) == -1) {
return -1;
}
p = tmpldir_list;
while (p != NULL) {
sprintf(buf, "%s/%s", dir, p->name);
scan_template_dir(buf, p->name);
p = p->next;
}
qsort(tmpl_list, tmpl_pos, sizeof tmpl_list[0], tmplcmp);
return 0;
}
/*
* Free all the memory used by the template cache. Sets the cache to
* the empty state.
*/
static void free_template_list()
{
struct tmpldir *p;
free(tmpl_list);
p = tmpldir_list;
while (p != NULL) {
struct tmpldir *np = p->next;
free(p);
p = np;
}
tmpl_list = NULL;
tmpldir_list = NULL;
tmpl_pos = 0;
tmpl_len = 0;
return;
}
char *subdirs[] = {
"3025",
"3050",
"3055",
"3058",
"3060",
"2750",
"Aero",
"MISC",
"Clan",
"ClanVehicles",
"Clan2nd",
"ClanAero",
"Custom",
"Solaris",
"Vehicles",
"MFNA",
"Infantry",
NULL
};
void mechrep_Rloadnew(dbref player, void *data, char *buffer)
{
char *args[1];
MECHREP_COMMON(1);
if (mech_parseattributes(buffer, args, 1) == 1)
if (mech_loadnew(player, mech, args[0]) == 1) {
muxevent_remove_data((void *) mech);
clear_mech_from_LOS(mech);
notify(player, "Template loaded.");
return;
}
notify(player, "Unable to read that template.");
}
void clear_mech(MECH * mech, int flag)
{
int i, j;
mech->brief = 1;
bzero(&mech->rd, sizeof(mech_rd));
bzero(&mech->ud, sizeof(mech_ud));
MechSpotter(mech) = -1;
MechTarget(mech) = -1;
MechChargeTarget(mech) = -1;
MechChargeTimer(mech) = 0;
MechChargeDistance(mech) = 0;
MechSwarmTarget(mech) = -1;
MechDFATarget(mech) = -1;
MechTargX(mech) = -1;
MechStatus(mech) = 0;
MechTargY(mech) = -1;
MechPilot(mech) = -1;
MechAim(mech) = NUM_SECTIONS;
StopBurning(mech);
if (flag) {
for (i = 0; i < NUM_TICS; i++)
for (j = 0; j < TICLONGS; j++)
mech->tic[i][j] = 0;
for (i = 0; i < FREQS; i++) {
mech->freq[i] = 0;
mech->freqmodes[i] = 0;
mech->chantitle[i][0] = 0;
}
}
}
char *mechref_path(char *id)
{
static char openfile[1024];
FILE *fp;
int i = 0; /* this int has double use... ugly, but effective */
/*
* If the template name doesn't have slash search for it in the
* template name cache.
*/
redo:
if (strchr(id, '/') == NULL && (tmpl_list != NULL ||
scan_templates(MECH_PATH) != -1)) {
struct tmpldirent *ent;
struct tmpldirent key;
strncpy(key.name, id, CACHE_MAXNAME);
key.name[CACHE_MAXNAME] = '\0';
ent =
bsearch(&key, tmpl_list, tmpl_pos, sizeof tmpl_list[0],
tmplcmp);
if (ent == NULL) {
return NULL;
}
if (ent->dir == NULL) {
sprintf(openfile, "%s/%s", MECH_PATH, ent->name);
} else {
sprintf(openfile, "%s/%s/%s", MECH_PATH, ent->dir, ent->name);
}
if (access(openfile, R_OK) != 0) {
/* The file is missing (or unreadable)
invalidate the cache and try again,
if *that* fails, fall back to the old version. */
if (!i) {
i = 1;
free_template_list();
goto redo;
} else
goto oldstyle;
}
return openfile;
}
oldstyle:
/*
* Look up a template name the old way...
*/
sprintf(openfile, "%s/%s", MECH_PATH, id);
fp = fopen(openfile, "r");
for (i = 0; !fp && subdirs[i]; i++) {
sprintf(openfile, "%s/%s/%s", MECH_PATH, subdirs[i], id);
fp = fopen(openfile, "r");
}
if (fp) {
fclose(fp);
return openfile;
}
return NULL;
}
int load_mechdata2(dbref player, MECH * mech, char *id)
{
FILE *fp = NULL;
char *filename;
filename = mechref_path(id);
if (!filename)
return 0;
if (!(fp = fopen(filename, "r")))
return 0;
fclose(fp);
return load_template(player, mech, filename) >= 0 ? 1 : 0;
}
extern int num_def_weapons;
int unable_to_find_proper_type(int i)
{
if (!i)
return 0;
if (IsWeapon(i)) {
if (i > (num_def_weapons))
return 1;
}
if (IsAmmo(i)) {
if ((Ammo2Weapon(i) + 1) > (num_def_weapons))
return 1;
}
if (IsSpecial(i))
if (Special2I(i) >= count_special_items())
return 1;
return 0;
}
int load_mechdata(MECH * mech, char *id)
{
FILE *fp = NULL;
int i, j, k, t;
int i1, i2, i3, i4, i5, i6;
char *filename;
filename = mechref_path(id);
TEMPLATE_GERR(filename == NULL, tprintf("No matching file for '%s'.",
id));
if (filename)
fp = fopen(filename, "r");
TEMPLATE_GERR(!fp, tprintf("Unable to open file %s (%s)!", filename,
id));
strncpy(MechType_Ref(mech), id, 15);
MechType_Ref(mech)[14] = '\0';
TEMPLATE_GERR(fscanf(fp, "%d %d %d %d %d %f %f %d\n", &i1, &i2, &i3,
&i4, &i5, &MechMaxSpeed(mech), &MechJumpSpeed(mech), &i6) < 8,
"Old template loading system: %s is invalid template file.", id);
MechTons(mech) = i1;
MechTacRange(mech) = i2;
MechLRSRange(mech) = i3;
MechScanRange(mech) = i4;
MechRealNumsinks(mech) = i5;
#define DROP(a) \
if (i6 & a) i6 &= ~a
DROP(32768); /* Quad */
DROP(16384); /* Salvagetech */
DROP(8192); /* Cargotech */
DROP(4196); /* Watergun */
MechSpecials(mech) = i6;
for (k = 0; k < NUM_SECTIONS; k++) {
i = k;
if (MechType(mech) == 4) {
switch (k) {
case 3:
i = 4;
break;
case 4:
i = 5;
break;
case 5:
i = 3;
break;
}
}
TEMPLATE_GERR(fscanf(fp, "%d %d %d %d\n", &i1, &i2, &i3, &i4) < 4,
"Insufficient data reading section %d!", i);
MechSections(mech)[i].recycle = 0;
SetSectArmor(mech, i, i1);
SetSectOArmor(mech, i, i1);
SetSectInt(mech, i, i2);
SetSectOInt(mech, i, i2);
SetSectRArmor(mech, i, i3);
SetSectORArmor(mech, i, i3);
/* Remove all rampant AXEs from the arms themselves, we do
things differently here */
if (i4 & 4)
i4 &= ~4;
MechSections(mech)[i].config = i4;
for (j = 0; j < NUM_CRITICALS; j++) {
TEMPLATE_GERR(fscanf(fp, "%d %d %d\n", &i1, &i2, &i3) < 3,
"Insufficient data reading critical %d/%d!", i, j);
MechSections(mech)[i].criticals[j].type = i1;
TEMPLATE_GERR(unable_to_find_proper_type(GetPartType(mech, i,
j)), "Invalid datatype at %d/%d!", i, j);
if (IsSpecial(i1))
i1 += SPECIAL_BASE_INDEX - OSPECIAL_BASE_INDEX;
if (IsWeapon(GetPartType(mech, i, j)) &&
IsAMS((t = Weapon2I(GetPartType(mech, i, j))))) {
if (MechWeapons[t].special & CLAT)
MechSpecials(mech) |= CL_ANTI_MISSILE_TECH;
else
MechSpecials(mech) |= IS_ANTI_MISSILE_TECH;
}
MechSections(mech)[i].criticals[j].data = i2;
MechSections(mech)[i].criticals[j].firemode = i3;
}
}
if (fscanf(fp, "%d %d\n", &i1, &i2) == 2) {
MechType(mech) = i1;
TEMPLATE_GERR(MechType(mech) > CLASS_LAST, "Invalid 'mech type!");
MechMove(mech) = i2;
TEMPLATE_GERR(MechMove(mech) > MOVENEMENT_LAST,
"Invalid movenement type!");
}
if (fscanf(fp, "%d\n", &i1) != 1)
MechRadioRange(mech) = DEFAULT_RADIORANGE;
else
MechRadioRange(mech) = i1;
fclose(fp);
return 1;
}
#undef LOADNEW_LOADS_OLD_IF_FAIL
#define LOADNEW_LOADS_MUSE_FORMAT
int mech_loadnew(dbref player, MECH * mech, char *id)
{
char mech_origid[100];
strncpy(mech_origid, MechType_Ref(mech), 99);
mech_origid[99] = '\0';
if (!strcmp(mech_origid, id)) {
clear_mech(mech, 0);
if (load_mechdata2(player, mech, id) <= 0)
return load_mechdata(mech, id) > 0;
return 1;
} else {
clear_mech(mech, 1);
if (load_mechdata2(player, mech, id) < 1)
#ifdef LOADNEW_LOADS_MUSE_FORMAT
if (load_mechdata(mech, id) < 1)
#endif
#ifdef LOADNEW_LOADS_OLD_IF_FAIL
if (load_mechdata2(player, mech, mech_origid) < 1)
#ifdef LOADNEW_LOADS_MUSE_FORMAT
if (load_mechdata(mech, mech_origid) < 1)
#endif
#endif
return 0;
}
return 1;
}
void mechrep_Rrestore(dbref player, void *data, char *buffer)
{
char *c;
MECHREP_COMMON(1);
c = silly_atr_get(mech->mynum, A_MECHREF);
DOCHECK(!c || !*c, "Sorry, I don't know what type of mech this is");
DOCHECK(mech_loadnew(player, mech, c) == 1, "Restoration complete!");
notify(player, "Unable to restore this mech!.");
}
void mechrep_Rsavetemp(dbref player, void *data, char *buffer)
{
char *args[1];
FILE *fp;
char openfile[512];
int i, j;
MECHREP_COMMON(1);
free_template_list();
DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
"You must specify a template name!");
DOCHECK(strstr(args[0], "/"), "Invalid file name!");
notify(player, tprintf("Saving %s", args[0]));
sprintf(openfile, "%s/", MECH_PATH);
strcat(openfile, args[0]);
DOCHECK(!(fp =
fopen(openfile, "w")),
"Unable to open/create mech file! Sorry.");
fprintf(fp, "%d %d %d %d %d %.2f %.2f %d\n", MechTons(mech),
MechTacRange(mech), MechLRSRange(mech), MechScanRange(mech),
MechRealNumsinks(mech), MechMaxSpeed(mech), MechJumpSpeed(mech),
MechSpecials(mech));
for (i = 0; i < NUM_SECTIONS; i++) {
fprintf(fp, "%d %d %d %d\n", GetSectArmor(mech, i),
GetSectInt(mech, i), GetSectRArmor(mech, i),
MechSections(mech)[i].config);
for (j = 0; j < NUM_CRITICALS; j++) {
fprintf(fp, "%d %d %d\n",
MechSections(mech)[i].criticals[j].type,
MechSections(mech)[i].criticals[j].data,
MechSections(mech)[i].criticals[j].firemode);
}
}
fprintf(fp, "%d %d\n", MechType(mech), MechMove(mech));
fprintf(fp, "%d\n", MechRadioRange(mech));
fclose(fp);
notify(player, "Saving complete!");
}
void mechrep_Rsavetemp2(dbref player, void *data, char *buffer)
{
char *args[1];
char openfile[512];
MECHREP_COMMON(1);
free_template_list();
DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
"You must specify a template name!");
DOCHECK(strstr(args[0], "/"), "Invalid file name!");
notify(player, tprintf("Saving %s", args[0]));
sprintf(openfile, "%s/", MECH_PATH);
strcat(openfile, args[0]);
DOCHECK(mech_weight_sub(GOD, mech, -1) > (MechTons(mech) * 1024),
"Error saving template: Too heavy.");
DOCHECK(save_template(player, mech, args[0], openfile) < 0,
"Error saving the template file!");
notify(player, "Saving complete!");
}
void mechrep_Rsetarmor(dbref player, void *data, char *buffer)
{
char *args[4];
int argc;
int index;
int temp;
MECHREP_COMMON(1);
argc = mech_parseattributes(buffer, args, 4);
DOCHECK(!argc, "Invalid number of arguments!");
index =
ArmorSectionFromString(MechType(mech), MechMove(mech), args[0]);
if (index == -1) {
notify(player, "Not a legal area. Must be HEAD, CTORSO");
notify(player, "LTORSO, RTORSO, RLEG, LLEG, RARM, LARM");
notify(player, "TURRET, ROTOR, RSIDE, LSIDE, FRONT, AFT");
return;
}
argc--;
if (argc) {
temp = atoi(args[1]);
if (temp < 0)
notify(player, "Invalid armor value!");
else {
notify(player, "Front armor set!");
SetSectArmor(mech, index, temp);
SetSectOArmor(mech, index, temp);
}
argc--;
}
if (argc) {
temp = atoi(args[2]);
if (temp < 0)
notify(player, "Invalid Internal armor value!");
else {
notify(player, "Internal armor set!");
SetSectInt(mech, index, temp);
SetSectOInt(mech, index, temp);
}
argc--;
}
if (argc) {
temp = atoi(args[3]);
if (index == CTORSO || index == RTORSO || index == LTORSO) {
if (temp < 0)
notify(player, "Invalid Rear armor value!");
else {
notify(player, "Rear armor set!");
SetSectRArmor(mech, index, temp);
SetSectORArmor(mech, index, temp);
}
} else
notify(player, "Only the torso can have rear armor.");
}
}
/*
* Handles the adding of weapons via the 'addweap' command in the form of:
* addweap <weap> <loc> <crits> [<flags>]
* Current Flags: O = OS, T = TC, R = Rear
*/
void mechrep_Raddweap(dbref player, void *data, char *buffer)
{
char *args[20]; /* The argument array */
int argc; /* Count of arguments */
int index; /* Used to determine section validity */
int weapindex; /* Weapon index number */
int weapnumcrits; /* Number of crits the desired weapon occupies. */
int weaptype; /* The weapon type */
int loop, temp; /* Loop Counters */
int isrear = 0; /* Rear mounted? */
int istc = 0; /* Is the weap TC'd? */
int isoneshot = 0; /* If 1, weapon is a One-Shot (OS) Weap */
int isrocket = 0; /* Is this a rocket launcher? */
int argstoiter; /* Holder for figuring out how many args to scan */
char flagholder; /* Holder for flag comparisons */
MECHREP_COMMON(1);
argc = mech_parseattributes(buffer, args, 20);
DOCHECK(argc < 3, "Invalid number of arguments!")
index = ArmorSectionFromString(MechType(mech), MechMove(mech), args[1]);
if (index == -1) {
notify_printf(player, "Not a legal area. Must be HEAD, CTORSO");
notify_printf(player, "LTORSO, RTORSO, RLEG, LLEG, RARM, LARM");
notify_printf(player, "TURRET, ROTOR, RSIDE, LSIDE, FRONT, AFT");
return;
}
weapindex = WeaponIndexFromString(args[0]);
if (weapindex == -1) {
notify_printf(player, "That is not a valid weapon!");
DumpWeapons(player);
return;
}
/*
* There are always 3 arguments that preceed flags.
* addweap <weap> <loc> <crit>, 0, 1, and 2 respectively in args[][].
* By subtracting 3, we figure out how many of our arguments are actually
* flags.
*/
argstoiter = argc - 3;
/*
* Now we take those additional flags and look for matches. argc is
* decremented to keep track of how many of our arguments are crit
* locations.
*/
for (loop = 0; loop < argstoiter; loop++) {
flagholder = toupper(args[3 + loop][0]);
if (flagholder == 'T') {
/* Targeting Computer */
istc = 1;
} else if (flagholder == 'R') {
/* Rear Mounted */
isrear = 1;
} else if (flagholder == 'O') {
/* One-Shot */
isoneshot = 1;
}
/*
* If it's a letter, it's not a crit location. If a
* player throws numbers in with the crit flags, then
* they'll see error messages about crit counts. Need
* to find a better way to fool-proof this.
*/
if (isalpha(flagholder))
argc--;
} /* end for */
/* Chop off the first the first two redundant args. */
argc -= 2;
weapnumcrits = GetWeaponCrits(mech, weapindex);
/* Check to see if player gives enough crits and start adding if so. */
if (argc < weapnumcrits) {
notify_printf(player,
"Not enough critical slots specified! (Given: %i, Needed: %i)",
argc, weapnumcrits);
} else if (argc > weapnumcrits) {
notify_printf(player,
"Too many critical slots specified! (Given: %i, Needed: %i)",
argc, weapnumcrits);
} else {
for (loop = 0; loop < GetWeaponCrits(mech, weapindex); loop++) {
temp = atoi(args[2 + loop]);
temp--; /* From 1 based to 0 based */
DOCHECK(temp < 0 ||
temp > NUM_CRITICALS, "Bad critical location!");
MechSections(mech)[index].criticals[temp].type =
(I2Weapon(weapindex));
MechSections(mech)[index].criticals[temp].firemode = 0;
MechSections(mech)[index].criticals[temp].ammomode = 0;
/* If this is a Rocket Launcher, use isrocket to set the OS flag */
if (MechWeapons[weapindex].special & ROCKET)
isrocket = 1;
if (isrear)
MechSections(mech)[index].criticals[temp].firemode |=
REAR_MOUNT;
if (istc)
MechSections(mech)[index].criticals[temp].firemode |=
ON_TC;
/* Rockets are OS too */
if (isoneshot || isrocket)
MechSections(mech)[index].criticals[temp].firemode |=
OS_MODE;
}
if (IsAMS(weapindex)) {
if (MechWeapons[weapindex].special & CLAT)
MechSpecials(mech) |= CL_ANTI_MISSILE_TECH;
else
MechSpecials(mech) |= IS_ANTI_MISSILE_TECH;
}
notify_printf(player, "Weapon added.");
}
} /* end mechrep_Raddweap() */
void mechrep_Rreload(dbref player, void *data, char *buffer)
{
char *args[4];
int argc;
int index;
int weapindex;
int subsect;
MECHREP_COMMON(1);
argc = mech_parseattributes(buffer, args, 4);
DOCHECK(argc <= 2, "Invalid number of arguments!");
weapindex = WeaponIndexFromString(args[0]);
if (weapindex == -1) {
notify(player, "That is not a valid weapon!");
DumpWeapons(player);
return;
}
index =
ArmorSectionFromString(MechType(mech), MechMove(mech), args[1]);
if (index == -1) {
notify(player, "Not a legal area. Must be HEAD, CTORSO");
notify(player, "LTORSO, RTORSO, RLEG, LLEG, RARM, LARM");
notify(player, "TURRET, ROTOR, RSIDE, LSIDE, FRONT, AFT");
return;
}
subsect = atoi(args[2]);
subsect--; /* from 1 based to 0 based */
DOCHECK(subsect < 0 ||
subsect >= CritsInLoc(mech, index), "Critslot out of range!");
if (MechWeapons[weapindex].ammoperton == 0)
notify(player, "That weapon doesn't require ammo!");
else {
MechSections(mech)[index].criticals[subsect].type =
I2Ammo(weapindex);
MechSections(mech)[index].criticals[subsect].firemode = 0;
MechSections(mech)[index].criticals[subsect].ammomode = 0;
if (argc > 3)
switch (toupper(args[3][0])) {
case 'W':
MechSections(mech)[index].criticals[subsect].ammomode |=
SWARM_MODE;
break;
case '1':
MechSections(mech)[index].criticals[subsect].ammomode |=
SWARM1_MODE;
break;
case 'I':
MechSections(mech)[index].criticals[subsect].ammomode |=
INFERNO_MODE;
break;
case 'L':
MechSections(mech)[index].criticals[subsect].ammomode |=
LBX_MODE;
break;
case 'A':
MechSections(mech)[index].criticals[subsect].ammomode |=
ARTEMIS_MODE;
break;
case 'N':
MechSections(mech)[index].criticals[subsect].ammomode |=
NARC_MODE;
break;
case 'C':
MechSections(mech)[index].criticals[subsect].ammomode |=
CLUSTER_MODE;
break;
case 'M':
MechSections(mech)[index].criticals[subsect].ammomode |=
MINE_MODE;
break;
case 'S':
MechSections(mech)[index].criticals[subsect].ammomode |=
SMOKE_MODE;
break;
case 'X':
MechSections(mech)[index].criticals[subsect].ammomode |=
INARC_EXPLO_MODE;
break;
case 'Y':
MechSections(mech)[index].criticals[subsect].ammomode |=
INARC_HAYWIRE_MODE;
break;
case 'E':
MechSections(mech)[index].criticals[subsect].ammomode |=
INARC_ECM_MODE;
break;
case 'R':
MechSections(mech)[index].criticals[subsect].ammomode |=
AC_AP_MODE;
break;
case 'F':
MechSections(mech)[index].criticals[subsect].ammomode |=
AC_FLECHETTE_MODE;
break;
case 'D':
MechSections(mech)[index].criticals[subsect].ammomode |=
AC_INCENDIARY_MODE;
break;
case 'P':
MechSections(mech)[index].criticals[subsect].ammomode |=
AC_PRECISION_MODE;
break;
}
MechSections(mech)[index].criticals[subsect].data =
FullAmmo(mech, index, subsect);
notify(player, "Weapon loaded!");
}
}
void mechrep_Rrepair(dbref player, void *data, char *buffer)
{
char *args[4];
int argc;
int index;
int temp;
MECHREP_COMMON(1);
argc = mech_parseattributes(buffer, args, 4);
DOCHECK(argc <= 2, "Invalid number of arguments!");
index =
ArmorSectionFromString(MechType(mech), MechMove(mech), args[0]);
if (index == -1) {
notify(player, "Not a legal area. Must be HEAD, CTORSO");
notify(player, "LTORSO, RTORSO, RLEG, LLEG, RARM, LARM");
notify(player, "TURRET, ROTOR, RSIDE, LSIDE, FRONT, AFT");
return;
}
temp = atoi(args[2]);
DOCHECK(temp < 0, "Illegal value for armor!");
switch (args[1][0]) {
case 'A':
case 'a':
/* armor */
SetSectArmor(mech, index, temp);
notify(player, "Armor repaired!");
break;
case 'I':
case 'i':
/* internal */
SetSectInt(mech, index, temp);
notify(player, "Internal structure repaired!");
break;
case 'C':
case 'c':
/* criticals */
temp--;
if (temp >= 0 && temp < NUM_CRITICALS) {
MechSections(mech)[index].criticals[temp].data = 0;
notify(player, "Critical location repaired!");
} else {
notify(player, "Critical Location out of range!");
}
break;
case 'R':
case 'r':
/* rear */
if (index == CTORSO || index == LTORSO || index == RTORSO) {
SetSectRArmor(mech, index, temp);
notify(player, "Rear armor repaired!");
} else {
notify(player,
"Only the center, rear and left torso have rear armor!");
}
break;
default:
notify(player,
"Illegal Type-> must be ARMOR, INTERNAL, CRIT, REAR");
return;
}
}
/*
ADDSP <ITEM> <LOCATION> <SUBSECT> [<DATA>]
*/
void mechrep_Raddspecial(dbref player, void *data, char *buffer)
{
char *args[4];
int argc;
int index;
int itemcode;
int subsect;
int newdata;
int max;
MECHREP_COMMON(1);
argc = mech_parseattributes(buffer, args, 4);
DOCHECK(argc <= 2, "Invalid number of arguments!");
itemcode = FindSpecialItemCodeFromString(args[0]);
if (itemcode == -1)
if (strcasecmp(args[0], "empty")) {
notify(player, "That is not a valid special object!");
DumpMechSpecialObjects(player);
return;
}
index =
ArmorSectionFromString(MechType(mech), MechMove(mech), args[1]);
if (index == -1) {
notify(player, "Not a legal area. Must be HEAD, CTORSO");
notify(player, "LTORSO, RTORSO, RLEG, LLEG, RARM, LARM");
notify(player, "TURRET, ROTOR, RSIDE, LSIDE, FRONT, AFT");
return;
}
subsect = atoi(args[2]);
subsect--;
max = CritsInLoc(mech, index);
DOCHECK(subsect < 0 || subsect >= max, "Critslot out of range!");
if (argc == 4)
newdata = atoi(args[3]);
else
newdata = 0;
MechSections(mech)[index].criticals[subsect].type =
itemcode < 0 ? 0 : I2Special(itemcode);
MechSections(mech)[index].criticals[subsect].data = newdata;
switch (itemcode) {
case CASE:
MechSections(mech)[(MechType(mech) ==
CLASS_VEH_GROUND) ? BSIDE : index].config |= CASE_TECH;
notify(player, "CASE Technology added to section.");
break;
case TRIPLE_STRENGTH_MYOMER:
MechSpecials(mech) |= TRIPLE_MYOMER_TECH;
notify(player,
"Triple Strength Myomer Technology added to 'Mech.");
break;
case MASC:
MechSpecials(mech) |= MASC_TECH;
notify(player,
"Myomer Accelerator Signal Circuitry added to 'Mech.");
break;
case C3_MASTER:
MechSpecials(mech) |= C3_MASTER_TECH;
notify(player, "C3 Command Unit added to 'Mech.");
break;
case C3_SLAVE:
MechSpecials(mech) |= C3_SLAVE_TECH;
notify(player, "C3 Slave Unit added to 'Mech.");
break;
case ARTEMIS_IV:
MechSections(mech)[index].criticals[subsect].data--;
MechSpecials(mech) |= ARTEMIS_IV_TECH;
notify(player, "Artemis IV Fire-Control System added to 'Mech.");
notify(player,
tprintf
("System will control the weapon which starts at slot %d.",
newdata));
break;
case ECM:
MechSpecials(mech) |= ECM_TECH;
notify(player, "Guardian ECM Suite added to 'Mech.");
break;
case ANGELECM:
MechSpecials2(mech) |= ANGEL_ECM_TECH;
notify(player, "Angel ECM Suite added to 'Mech.");
break;
case BEAGLE_PROBE:
MechSpecials(mech) |= BEAGLE_PROBE_TECH;
notify(player, "Beagle Active Probe added to 'Mech.");
break;
case TAG:
MechSpecials2(mech) |= TAG_TECH;
notify(player, "TAG added to 'Mech.");
break;
case C3I:
MechSpecials2(mech) |= C3I_TECH;
notify(player, "Improved C3 added to 'Mech.");
break;
case BLOODHOUND_PROBE:
MechSpecials2(mech) |= BLOODHOUND_PROBE_TECH;
notify(player, "Bloodhound Active Probe added to 'Mech.");
break;
}
notify(player, "Critical slot filled.");
}
extern char *specials[];
extern char *specials2[];
extern char *infantry_specials[];
char *techstatus_func(MECH * mech)
{
return (MechSpecials(mech) ||
MechSpecials2(mech)) ? BuildBitString2(specials, specials2,
MechSpecials(mech), MechSpecials2(mech)) : "";
}
void mechrep_Rshowtech(dbref player, void *data, char *buffer)
{
int i;
char *techstring;
char location[20];
MECHREP_COMMON(1);
notify(player, "--------Advanced Technology--------");
if (MechSpecials(mech) & TRIPLE_MYOMER_TECH)
notify(player, "Triple Strength Myomer");
if (MechSpecials(mech) & MASC_TECH)
notify(player, "Myomer Accelerator Signal Circuitry");
for (i = 0; i < NUM_SECTIONS; i++)
if (MechSections(mech)[i].config & CASE_TECH) {
ArmorStringFromIndex(i, location, MechType(mech),
MechMove(mech));
notify(player,
tprintf("Cellular Ammunition Storage Equipment in %s",
location));
}
if (MechSpecials(mech) & CLAN_TECH) {
notify(player, "Mech is set to Clan Tech. This means:");
notify(player, " Mech automatically has Double Heat Sink Tech");
notify(player, " Mech automatically has CASE in all sections");
}
if (MechSpecials(mech) & DOUBLE_HEAT_TECH)
notify(player, "Mech uses Double Heat Sinks");
if (MechSpecials(mech) & CL_ANTI_MISSILE_TECH)
notify(player, "Clan style Anti-Missile System");
if (MechSpecials(mech) & IS_ANTI_MISSILE_TECH)
notify(player, "Inner Sphere style Anti-Missile System");
if (MechSpecials(mech) & FLIPABLE_ARMS)
notify(player, "The arms may be flipped into the rear firing arc");
if (MechSpecials(mech) & C3_MASTER_TECH)
notify(player, "C3 Command Computer");
if (MechSpecials(mech) & C3_SLAVE_TECH)
notify(player, "C3 Slave Computer");
if (MechSpecials(mech) & ARTEMIS_IV_TECH)
notify(player, "Artemis IV Fire-Control System");
if (MechSpecials(mech) & ECM_TECH)
notify(player, "Guardian ECM Suite");
if (MechSpecials2(mech) & ANGEL_ECM_TECH)
notify(player, "Angel ECM Suite");
if (MechSpecials(mech) & BEAGLE_PROBE_TECH)
notify(player, "Beagle Active Probe");
if (MechSpecials2(mech) & TAG_TECH)
notify(player, "Target Aquisition Gear");
if (MechSpecials2(mech) & C3I_TECH)
notify(player, "Improved C3");
if (MechSpecials2(mech) & BLOODHOUND_PROBE_TECH)
notify(player, "Bloodhound Active Probe");
if (MechSpecials(mech) & ICE_TECH)
notify(player, "It has ICE engine");
/* Infantry related stuff */
if (MechInfantrySpecials(mech) & INF_SWARM_TECH)
notify(player, "Can swarm enemy units");
if (MechInfantrySpecials(mech) & INF_MOUNT_TECH)
notify(player, "Can mount friendly units");
if (MechInfantrySpecials(mech) & INF_ANTILEG_TECH)
notify(player, "Can do anti-leg attacks");
if (MechInfantrySpecials(mech) & CS_PURIFIER_STEALTH_TECH)
notify(player, "Has CS Purifier Stealth");
if (MechInfantrySpecials(mech) & DC_KAGE_STEALTH_TECH)
notify(player, "Has DC Kage Stealth");
if (MechInfantrySpecials(mech) & FWL_ACHILEUS_STEALTH_TECH)
notify(player, "Has FWL Achileus Stealth");
if (MechInfantrySpecials(mech) & FC_INFILTRATOR_STEALTH_TECH)
notify(player, "Has FC Infiltrator Stealth");
if (MechInfantrySpecials(mech) & FC_INFILTRATORII_STEALTH_TECH)
notify(player, "Has FC InfiltratorII Stealth");
if (MechInfantrySpecials(mech) & MUST_JETTISON_TECH)
notify(player,
"Must jettison backpack before jumping/using specials");
if (MechInfantrySpecials(mech) & CAN_JETTISON_TECH)
notify(player, "Can jettison backpack");
notify(player, "Brief version (May have something previous hadn't):");
techstring = mechrep_gettechstring(mech);
if (techstring && techstring[0])
notify(player, techstring);
else
notify(player, "-");
}
char * mechrep_gettechstring(MECH *mech)
{
return BuildBitString3(specials, specials2, infantry_specials,
MechSpecials(mech), MechSpecials2(mech),
MechInfantrySpecials(mech));
}
void mechrep_Rdeltech(dbref player, void *data, char *buffer)
{
int i, j;
int Type;
int nv, nv2;
MECHREP_COMMON(1);
/* Compare what the user gave to our specials lists */
nv = BuildBitVector(specials, buffer);
nv2 = BuildBitVector(specials2, buffer);
/* Make sure what they gave was valid */
if (((nv < 0) && (nv2 < 0)) && (strcasecmp(buffer, "all") != 0) &&
(strcasecmp(buffer, "Case") != 0)) {
notify(player, "Invalid tech: Available techs:");
notify(player, "\tAll");
notify(player, "\tCase");
for (nv = 0; specials[nv]; nv++)
notify(player, tprintf("\t%s", specials[nv]));
for (nv = 0; specials2[nv]; nv++)
notify(player, tprintf("\t%s", specials2[nv]));
return;
}
/* Check to see if user specified anything */
if (((!nv) && (!nv2)) && (strcasecmp(buffer, "all") != 0) &&
(strcasecmp(buffer, "Case") != 0)) {
notify(player, "Nothing specified");
return;
}
/* Check to see if user specified 'ALL' */
if (strcasecmp(buffer, "all") == 0) {
for (i = 0; i < NUM_SECTIONS; i++) {
if ((MechSections(mech)[i].config & CASE_TECH)
|| (MechSpecials(mech) & TRIPLE_MYOMER_TECH)
|| (MechSpecials(mech) & MASC_TECH)) {
for (j = 0; j < NUM_CRITICALS; j++) {
Type = MechSections(mech)[i].criticals[j].type;
if (Type == I2Special((CASE))
|| Type == I2Special((TRIPLE_STRENGTH_MYOMER))
|| Type == I2Special((MASC))) {
MechSections(mech)[i].criticals[j].type = EMPTY;
}
}
MechSections(mech)[i].config &= ~CASE_TECH;
}
}
MechSpecials(mech) = 0;
MechSpecials2(mech) = 0;
notify(player, "All Advanced Technology Removed");
return;
}
if (strcasecmp(buffer, "Case") == 0) {
for (i = 0; i < NUM_SECTIONS; i++) {
if (MechSections(mech)[i].config & CASE_TECH) {
for (j = 0; j < NUM_CRITICALS; j++) {
Type = MechSections(mech)[i].criticals[j].type;
if (Type == I2Special((CASE))) {
MechSections(mech)[i].criticals[j].type = EMPTY;
}
}
MechSections(mech)[i].config &= ~CASE_TECH;
}
}
notify(player, "Case Technology Removed");
return;
}
if (nv > 0) {
if (strcasecmp(buffer, "TripleMyomerTech") == 0) {
if (MechSpecials(mech) & TRIPLE_MYOMER_TECH) {
for (i = 0; i < NUM_SECTIONS; i++) {
for (j = 0; j < NUM_CRITICALS; j++) {
Type = MechSections(mech)[i].criticals[j].type;
if (Type == I2Special((TRIPLE_STRENGTH_MYOMER))) {
MechSections(mech)[i].criticals[j].type = EMPTY;
}
}
}
}
} else if (strcasecmp(buffer, "Masc") == 0) {
if (MechSpecials(mech) & MASC_TECH) {
for (i = 0; i < NUM_SECTIONS; i++) {
for (j = 0; j < NUM_CRITICALS; j++) {
Type = MechSections(mech)[i].criticals[j].type;
if (Type == I2Special((MASC))) {
MechSections(mech)[i].criticals[j].type = EMPTY;
}
}
}
}
}
MechSpecials(mech) &= ~nv;
notify(player, tprintf("%s Technology Removed", buffer));
} else {
MechSpecials2(mech) &= ~nv2;
notify(player, tprintf("%s Technology Removed", buffer));
}
return;
}
void mechrep_Raddtech(dbref player, void *data, char *buffer)
{
int nv, nv2;
MECHREP_COMMON(1);
nv = BuildBitVector(specials, buffer);
nv2 = BuildBitVector(specials2, buffer);
if ((nv < 0) && (nv2 < 0)) {
notify(player, "Invalid tech: Available techs:");
for (nv = 0; specials[nv]; nv++)
notify(player, tprintf("\t%s", specials[nv]));
for (nv = 0; specials2[nv]; nv++)
notify(player, tprintf("\t%s", specials2[nv]));
return;
}
if ((!nv) && (!nv2)) {
notify(player, "Nothing set!");
return;
}
if (nv > 0) {
MechSpecials(mech) |= nv;
notify(player, tprintf("Set: %s", BuildBitString(specials, nv)));
} else {
MechSpecials2(mech) |= nv2;
notify(player, tprintf("Set: %s", BuildBitString(specials2, nv2)));
}
}
void mechrep_Rdelinftech(dbref player, void *data, char *buffer)
{
MECH *mech = (MECH *) data;
MechInfantrySpecials(mech) = 0;
notify(player, "Advanced Infantry Technology Deleted");
}
void mechrep_Raddinftech(dbref player, void *data, char *buffer)
{
int nv;
MECHREP_COMMON(1);
nv = BuildBitVector(infantry_specials, buffer);
if (nv < 0) {
notify(player, "Invalid infantry tech: Available techs:");
for (nv = 0; infantry_specials[nv]; nv++)
notify(player, tprintf("\t%s", infantry_specials[nv]));
return;
}
if (!nv) {
notify(player, "Nothing set!");
return;
}
if (nv > 0) {
MechInfantrySpecials(mech) |= nv;
notify(player, tprintf("Set: %s", BuildBitString(infantry_specials,
nv)));
}
}
void mechrep_setcargospace(dbref player, void *data, char *buffer)
{
char *args[2];
int argc;
int cargo;
int max;
MECHREP_COMMON(1);
argc = mech_parseattributes(buffer, args, 2);
DOCHECK(argc != 2, "Invalid number of arguements!");
cargo = (atoi(args[0]) * 50);
DOCHECK(cargo < 0 || cargo > 100000, "Doesn't that seem excessive?");
CargoSpace(mech) = cargo;
max = (atoi(args[1]));
max = (BOUNDED(1,max,100));
CarMaxTon(mech) = (char) max;
notify(player, tprintf("%3.2f cargospace and %d tons of maxton space set.", (float) ((float) cargo / 100), (int) max));
}
MECH *load_refmech(char *reference)
{
static MECH cachemech;
static char cacheref[1024];
if (!strcmp(cacheref, reference))
return &cachemech;
if (mech_loadnew(GOD, &cachemech, reference) < 1) {
cacheref[0] = '\0';
return NULL;
}
strncpy(cacheref, reference, 1023);
cacheref[1023] = '\0';
return &cachemech;
}