00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <math.h>
00014 #include <sys/file.h>
00015
00016 #include "mech.h"
00017 #include "mech.events.h"
00018 #include "autopilot.h"
00019 #include "failures.h"
00020 #include "p.mech.los.h"
00021 #include "p.mine.h"
00022 #include "p.mech.utils.h"
00023 #include "p.mech.build.h"
00024 #include "p.mech.startup.h"
00025 #include "p.autopilot_command.h"
00026 #include "p.btechstats.h"
00027 #include "p.mech.sensor.h"
00028 #include "p.map.obj.h"
00029 #include "p.bsuit.h"
00030
00031 void sendchannelstuff(MECH * mech, int freq, char *msg);
00032
00033 const char *GetAmmoDesc_Model_Mode(int model, int mode)
00034 {
00035 if(mode & LBX_MODE)
00036 return " Shotgun";
00037 if(mode & ARTEMIS_MODE)
00038 return " Artemis IV";
00039 if(mode & NARC_MODE)
00040 return (MechWeapons[model].special & NARC) ? " Explosive" :
00041 " Narc compatible";
00042 if(mode & INARC_EXPLO_MODE)
00043 return " iExplosive";
00044 if(mode & INARC_HAYWIRE_MODE)
00045 return " Haywire";
00046 if(mode & INARC_ECM_MODE)
00047 return " ECM";
00048 if(mode & INARC_NEMESIS_MODE)
00049 return " Nemesis";
00050 if(mode & SWARM_MODE)
00051 return " Swarm";
00052 if(mode & SWARM1_MODE)
00053 return " Swarm1";
00054 if(mode & INFERNO_MODE)
00055 return " Inferno";
00056 if(mode & CLUSTER_MODE)
00057 return " Cluster";
00058 if(mode & SMOKE_MODE)
00059 return " Smoke";
00060 if(mode & MINE_MODE)
00061 return " Mine";
00062 if(mode & AC_AP_MODE)
00063 return " ArmorPiercing";
00064 if(mode & AC_FLECHETTE_MODE)
00065 return " Flechette";
00066 if(mode & AC_INCENDIARY_MODE)
00067 return " Incendiary";
00068 if(mode & AC_PRECISION_MODE)
00069 return " Precision";
00070 if(mode & STINGER_MODE)
00071 return " Stinger";
00072 if(mode & AC_CASELESS_MODE)
00073 return " Caseless";
00074 if(mode & SGUIDED_MODE)
00075 return " Sguided";
00076 return "";
00077 }
00078
00079 char GetWeaponAmmoModeLetter_Model_Mode(int model, int mode)
00080 {
00081 if(!(mode & AMMO_MODES))
00082 return ' ';
00083 if(mode & CLUSTER_MODE)
00084 return 'C';
00085 if(mode & SMOKE_MODE)
00086 return 'S';
00087 if(mode & MINE_MODE)
00088 return 'M';
00089 if(mode & LBX_MODE)
00090 return 'L';
00091 if(mode & ARTEMIS_MODE)
00092 return 'A';
00093 if(mode & NARC_MODE)
00094 return (MechWeapons[model].special & NARC) ? 'E' : 'N';
00095 if(mode & INARC_EXPLO_MODE)
00096 return 'X';
00097 if(mode & INARC_HAYWIRE_MODE)
00098 return 'Y';
00099 if(mode & INARC_ECM_MODE)
00100 return 'E';
00101 if(mode & INARC_NEMESIS_MODE)
00102 return 'Z';
00103 if(mode & INFERNO_MODE)
00104 return 'I';
00105 if(mode & SWARM_MODE)
00106 return 'W';
00107 if(mode & SWARM1_MODE)
00108 return '1';
00109 if(mode & AC_AP_MODE)
00110 return 'R';
00111 if(mode & AC_FLECHETTE_MODE)
00112 return 'F';
00113 if(mode & AC_INCENDIARY_MODE)
00114 return 'D';
00115 if(mode & AC_PRECISION_MODE)
00116 return 'P';
00117 if(mode & STINGER_MODE)
00118 return 'T';
00119 if(mode & AC_CASELESS_MODE)
00120 return 'U';
00121 if(mode & SGUIDED_MODE)
00122 return 'G';
00123 return ' ';
00124 }
00125
00126 char GetWeaponFireModeLetter_Model_Mode(int model, int mode)
00127 {
00128 if(!(mode & FIRE_MODES))
00129 return ' ';
00130 if(mode & HOTLOAD_MODE)
00131 return 'H';
00132 if(mode & ULTRA_MODE)
00133 return 'U';
00134 if(mode & RFAC_MODE)
00135 return 'F';
00136 if(mode & GATTLING_MODE)
00137 return 'G';
00138 if(mode & HEAT_MODE)
00139 return 'H';
00140 if(mode & RAC_TWOSHOT_MODE)
00141 return '2';
00142 if(mode & RAC_FOURSHOT_MODE)
00143 return '4';
00144 if(mode & RAC_SIXSHOT_MODE)
00145 return '6';
00146 return ' ';
00147 }
00148
00149 char GetWeaponAmmoModeLetter(MECH * mech, int loop, int crit)
00150 {
00151 return GetWeaponAmmoModeLetter_Model_Mode(Weapon2I(GetPartType(mech,
00152 loop,
00153 crit)),
00154 GetPartAmmoMode(mech, loop,
00155 crit));
00156 }
00157
00158 char GetWeaponFireModeLetter(MECH * mech, int loop, int crit)
00159 {
00160 return GetWeaponFireModeLetter_Model_Mode(Weapon2I(GetPartType(mech,
00161 loop,
00162 crit)),
00163 GetPartFireMode(mech, loop,
00164 crit));
00165 }
00166
00167 const char *GetMoveTypeID(int movetype)
00168 {
00169 static char buf[20];
00170
00171 switch (movetype) {
00172 case MOVE_QUAD:
00173 strcpy(buf, "QUAD");
00174 break;
00175 case MOVE_BIPED:
00176 strcpy(buf, "BIPED");
00177 break;
00178 case MOVE_TRACK:
00179 strcpy(buf, "TRACKED");
00180 break;
00181 case MOVE_WHEEL:
00182 strcpy(buf, "WHEELED");
00183 break;
00184 case MOVE_HOVER:
00185 strcpy(buf, "HOVER");
00186 break;
00187 case MOVE_VTOL:
00188 strcpy(buf, "VTOL");
00189 break;
00190 case MOVE_FLY:
00191 strcpy(buf, "FLY");
00192 break;
00193 case MOVE_HULL:
00194 strcpy(buf, "HULL");
00195 break;
00196 case MOVE_SUB:
00197 strcpy(buf, "SUBMARINE");
00198 break;
00199 case MOVE_FOIL:
00200 strcpy(buf, "HYDROFOIL");
00201 break;
00202 default:
00203 strcpy(buf, "Unknown");
00204 break;
00205 }
00206 return buf;
00207 }
00208
00209 struct {
00210 char *onmsg;
00211 char *offmsg;
00212 int flag;
00213 int infolvl;
00214 } temp_flag_info_struct[] = {
00215 {
00216 "DESTROYED", NULL, DESTROYED, 1}, {
00217 NULL, "SHUTDOWN", STARTED, 1}, {
00218 "Torso is 60 degrees right", NULL, TORSO_RIGHT, 0}, {
00219 "Torso is 60 degrees left", NULL, TORSO_LEFT, 0}, {
00220 NULL, NULL, 0}
00221 };
00222
00223 struct {
00224 int team;
00225 char *ccode;
00226 } obs_team_color[] = {
00227 {
00228 1, "%cw"}, {
00229 2, "%cc"}, {
00230 3, "%cm"}, {
00231 4, "%cb"}, {
00232 5, "%cy"}, {
00233 6, "%cg"}, {
00234 7, "%cr"}, {
00235 8, "%ch%cx"}, {
00236 9, "%ch%cw"}, {
00237 10, "%ch%cc"}, {
00238 11, "%ch%cm"}, {
00239 12, "%ch%cb"}, {
00240 13, "%ch%cy"}, {
00241 14, "%ch%cg"}, {
00242 15, "%ch%cr"}, {
00243 0, "%ch%cw"}
00244 };
00245
00246 void Mech_ShowFlags(dbref player, MECH * mech, int spaces, int level)
00247 {
00248 char buf[MBUF_SIZE];
00249 int i;
00250
00251 for(i = 0; i < spaces; i++)
00252 buf[i] = ' ';
00253 buf[spaces] = 0;
00254
00255 if(MechStatus(mech) & COMBAT_SAFE) {
00256 strcpy(buf + spaces, "%cb%chCOMBAT SAFE%cn");
00257 notify(player, buf);
00258 }
00259 if(Fallen(mech)) {
00260 switch (MechMove(mech)) {
00261 case MOVE_BIPED:
00262 strcpy(buf + spaces, "%cr%chFALLEN%cn");
00263 break;
00264 case MOVE_QUAD:
00265 strcpy(buf + spaces, "%cr%chFALLEN%cn");
00266 break;
00267 case MOVE_TRACK:
00268 strcpy(buf + spaces, "%cr%chTRACK DESTROYED%cn");
00269 break;
00270 case MOVE_WHEEL:
00271 strcpy(buf + spaces, "%cr%chAXLE DESTROYED%cn");
00272 break;
00273 case MOVE_HOVER:
00274 strcpy(buf + spaces, "%cr%chLIFT FAN DESTROYED%cn");
00275 break;
00276 case MOVE_VTOL:
00277 strcpy(buf + spaces, "%cr%chROTOR DESTROYED%cn");
00278 break;
00279 case MOVE_FLY:
00280 strcpy(buf + spaces, "%cr%chENGINE DESTROYED%cn");
00281 break;
00282 case MOVE_HULL:
00283 strcpy(buf + spaces, "%cr%chENGINE ROOM DESTROYED%cn");
00284 break;
00285 case MOVE_SUB:
00286 strcpy(buf + spaces, "%cr%chENGINE ROOM DESTROYED%cn");
00287 break;
00288 case MOVE_FOIL:
00289 strcpy(buf + spaces, "%cr%chFOIL DESTROYED%cn");
00290 break;
00291 }
00292 notify(player, buf);
00293 }
00294 if(IsHulldown(mech)) {
00295 strcpy(buf + spaces, "%cg%chHULLDOWN%cn");
00296 notify(player, buf);
00297 }
00298 if(MechDugIn(mech)) {
00299 strcpy(buf + spaces, "%cg%chDUG IN%cn");
00300 notify(player, buf);
00301 }
00302 if(Digging(mech)) {
00303 strcpy(buf + spaces, "%cgDIGGING IN%cn");
00304 notify(player, buf);
00305 }
00306 if(Staggering(mech)) {
00307 strcpy(buf + spaces, "%cr%chSTAGGERING%cn");
00308 notify(player, buf);
00309 }
00310 if(MechCritStatus(mech) & SLITE_DEST) {
00311 strcpy(buf + spaces, "%cr%chSEARCHLIGHT DESTROYED%cn");
00312 notify(player, buf);
00313 }
00314 if(MechLites(mech)) {
00315 strcpy(buf + spaces, "%cg%chSEARCHLIGHT ON%cn");
00316 notify(player, buf);
00317 } else if(MechLit(mech)) {
00318 strcpy(buf + spaces, "%cg%chILLUMINATED%cn");
00319 notify(player, buf);
00320 }
00321 if(Burning(mech) || Jellied(mech)) {
00322 strcpy(buf + spaces, "%cr%chON FIRE%cn");
00323 notify(player, buf);
00324 }
00325 if(MechCritStatus(mech) & HIDDEN) {
00326 strcpy(buf + spaces, tprintf("%%ch%%cgHIDDEN%%c"));
00327 notify(player, buf);
00328 }
00329 if(IsMechSwarmed(mech)) {
00330 strcpy(buf + spaces, "%cr%chSWARMED BY ENEMY SUITS%cn");
00331 notify(player, buf);
00332 }
00333 if(IsMechMounted(mech)) {
00334 strcpy(buf + spaces, "%cr%chMOUNTED BY FRIENDLY SUITS%cn");
00335 notify(player, buf);
00336 }
00337 if(MechSwarmTarget(mech) > 0) {
00338 if(getMech(MechSwarmTarget(mech))) {
00339 if(MechTeam(getMech(MechSwarmTarget(mech))) == MechTeam(mech))
00340 strcpy(buf + spaces, "%cg%chMOUNTED ON FRIENDLY UNIT%cn");
00341 else
00342 strcpy(buf + spaces, "%cg%chSWARMING ENEMY UNIT%cn");
00343
00344 notify(player, buf);
00345 }
00346 }
00347 #ifdef BT_MOVEMENT_MODES
00348 if(MechStatus2(mech) & DODGING) {
00349 strcpy(buf + spaces, tprintf("%%ch%%crDODGING%%c"));
00350 notify(player, buf);
00351 }
00352 if(MechStatus2(mech) & EVADING) {
00353 strcpy(buf + spaces, tprintf("%%ch%%crEVADING%%c"));
00354 notify(player, buf);
00355 }
00356 if(MechStatus2(mech) & SPRINTING) {
00357 strcpy(buf + spaces, tprintf("%%ch%%crSPRINTING%%c"));
00358 notify(player, buf);
00359 }
00360 if(MoveModeChange(mech)) {
00361 strcpy(buf + spaces, tprintf("%%ch%%cyCHANGING MOVEMENT MODE%%c"));
00362 notify(player, buf);
00363 }
00364 if(SideSlipping(mech)) {
00365 strcpy(buf + spaces, tprintf("%%ch%%cySIDESLIPPING%%c"));
00366 notify(player, buf);
00367 }
00368 if(MechTankCritStatus(mech) & CREW_STUNNED ||
00369 MechCritStatus(mech) & MECH_STUNNED) {
00370 strcpy(buf + spaces, "%ch%crSTUNNED%c");
00371 notify(player, buf);
00372 }
00373 #endif
00374 if(level == 0) {
00375 if(ECMProtected(mech)) {
00376 strcpy(buf + spaces, "%cg%chPROTECTED BY ECM%cn");
00377 notify(player, buf);
00378 }
00379 if(AngelECMProtected(mech)) {
00380 strcpy(buf + spaces, "%cg%chPROTECTED BY ANGEL ECM%cn");
00381 notify(player, buf);
00382 }
00383 if(ECMDisturbed(mech)) {
00384 strcpy(buf + spaces, "%cy%chAFFECTED BY ECM%cn");
00385 notify(player, buf);
00386 }
00387 if(AngelECMDisturbed(mech)) {
00388 strcpy(buf + spaces, "%cy%chAFFECTED BY ANGEL ECM%cn");
00389 notify(player, buf);
00390 }
00391 if(ECMCountered(mech)) {
00392 strcpy(buf + spaces, "%cy%chCOUNTERED BY ECCM%cn");
00393 notify(player, buf);
00394 }
00395 if(StealthArmorActive(mech)) {
00396 strcpy(buf + spaces, "%cg%chSTEALTH ARMOR ACTIVE%cn");
00397 notify(player, buf);
00398 }
00399 if(NullSigSysActive(mech)) {
00400 strcpy(buf + spaces, "%cg%chNULL SIGNATURE SYSTEM ACTIVE%cn");
00401 notify(player, buf);
00402 }
00403 if(checkAllSections(mech, NARC_ATTACHED)) {
00404 strcpy(buf + spaces, "%cy%chNARC POD ATTACHED%cn");
00405 notify(player, buf);
00406 }
00407 if(checkAllSections(mech, INARC_HOMING_ATTACHED)) {
00408 strcpy(buf + spaces, "%cy%chINARC HOMING POD ATTACHED%cn");
00409 notify(player, buf);
00410 }
00411 if(checkAllSections(mech, INARC_HAYWIRE_ATTACHED)) {
00412 strcpy(buf + spaces, "%cy%chINARC HAYWIRE POD ATTACHED%cn");
00413 notify(player, buf);
00414 }
00415 if(checkAllSections(mech, INARC_ECM_ATTACHED)) {
00416 strcpy(buf + spaces, "%cy%chINARC ECM POD ATTACHED%cn");
00417 notify(player, buf);
00418 }
00419 if(Extinguishing(mech)) {
00420 strcpy(buf + spaces, "%cy%chEXTINGUISHING FIRE%cn");
00421 notify(player, buf);
00422 }
00423 if(MechStatus2(mech) & AUTOTURN_TURRET) {
00424 strcpy(buf + spaces, "%cg%chTURRET AUTO-TURN ENGAGED%cn");
00425 notify(player, buf);
00426 }
00427 if(MechSections(mech)[RARM].specials & CARRYING_CLUB) {
00428 strcpy(buf + spaces, "%cg%chCARRYING CLUB - RIGHT ARM%cn");
00429 notify(player, buf);
00430 }
00431 if(MechSections(mech)[LARM].specials & CARRYING_CLUB) {
00432 strcpy(buf + spaces, "%cg%chCARRYING CLUB - LEFT ARM%cn");
00433 notify(player, buf);
00434 }
00435 }
00436 for(i = 0; temp_flag_info_struct[i].flag; i++)
00437 if(temp_flag_info_struct[i].infolvl >= level) {
00438 if(MechStatus(mech) & temp_flag_info_struct[i].flag) {
00439 if(temp_flag_info_struct[i].onmsg) {
00440 strcpy(buf + spaces, temp_flag_info_struct[i].onmsg);
00441 notify(player, buf);
00442 }
00443 } else {
00444 if(temp_flag_info_struct[i].offmsg) {
00445 strcpy(buf + spaces, temp_flag_info_struct[i].offmsg);
00446 notify(player, buf);
00447 }
00448 }
00449 }
00450 }
00451
00452 const char *GetArcID(MECH * mech, int arc)
00453 {
00454 static char buf[20];
00455 int mechlike = (MechType(mech) == CLASS_MECH ||
00456 MechType(mech) == CLASS_MW ||
00457 MechType(mech) == CLASS_BSUIT);
00458
00459 if(arc & FORWARDARC)
00460 strcpy(buf, "Forward");
00461 else if(arc & RSIDEARC)
00462 strcpy(buf, mechlike ? "Right Arm" : "Right Side");
00463 else if(arc & LSIDEARC)
00464 strcpy(buf, mechlike ? "Left Arm" : "Left Side");
00465 else if(arc & REARARC)
00466 strcpy(buf, "Rear");
00467 else
00468 strcpy(buf, "NO");
00469
00470 return buf;
00471 }
00472
00473 const char *GetMechToMechID_base(MECH * see, MECH * mech, int inlos)
00474 {
00475 char *mname;
00476 static char ids[SBUF_SIZE];
00477
00478 if(!Good_obj(mech->mynum))
00479 return "";
00480
00481 if(!inlos)
00482 mname = "something";
00483 else
00484 mname = silly_atr_get(mech->mynum, A_MECHNAME);
00485
00486 snprintf(ids, SBUF_SIZE, "%s [%s]", mname, MechIDS(mech, inlos &&
00487 MechTeam(see) ==
00488 MechTeam(mech)));
00489 ids[SBUF_SIZE - 1] = '\0';
00490 return ids;
00491 }
00492
00493 const char *GetMechToMechID(MECH * see, MECH * mech)
00494 {
00495 char *mname;
00496 int team;
00497 static char ids[SBUF_SIZE];
00498
00499 if(!mech ) {
00500 dprintk("bad mech");
00501 return "";
00502 }
00503 if(!see ) {
00504 dprintk("bad see");
00505 return "";
00506 }
00507 if(!Good_obj(mech->mynum))
00508 return "";
00509
00510 if(!InLineOfSight_NB(see, mech, 0, 0, 0)) {
00511 mname = "something";
00512 team = 0;
00513 } else {
00514 mname = silly_atr_get(mech->mynum, A_MECHNAME);
00515 team = (MechTeam(see) == MechTeam(mech));
00516 }
00517
00518 snprintf(ids, SBUF_SIZE, "%s [%s]", mname, MechIDS(mech, team));
00519 ids[SBUF_SIZE - 1] = '\0';
00520 return ids;
00521 }
00522
00523 const char *GetMechID(MECH * mech)
00524 {
00525 char *mname;
00526 static char ids[SBUF_SIZE];
00527
00528 if(!Good_obj(mech->mynum))
00529 return "";
00530
00531 mname = silly_atr_get(mech->mynum, A_MECHNAME);
00532 snprintf(ids, SBUF_SIZE, "%s [%s]", mname, MechIDS(mech, 0));
00533 ids[SBUF_SIZE - 1] = '\0';
00534 return ids;
00535 }
00536
00537 void mech_set_channelfreq(dbref player, void *data, char *buffer)
00538 {
00539 int chn = -1;
00540 int freq;
00541 MECH *mech = (MECH *) data;
00542 MECH *t;
00543 MAP *map = getMap(mech->mapindex);
00544 int i, j;
00545
00546
00547 cch(MECH_MAP);
00548 skipws(buffer);
00549 DOCHECK(!*buffer, "Invalid input!");
00550 chn = toupper(*buffer) - 'A';
00551 DOCHECK(chn < 0 || chn >= MFreqs(mech), "Invalid channel-letter!");
00552 buffer++;
00553 skipws(buffer);
00554 DOCHECK(!*buffer, "Invalid input!");
00555 DOCHECK(*buffer != '=', "Missing =!");
00556 buffer++;
00557 skipws(buffer);
00558 DOCHECK(!*buffer, "Invalid input!");
00559 freq = atoi(buffer);
00560 DOCHECK(!freq && strcmp(buffer, "0"), "Invalid frequency!");
00561 DOCHECK(freq < 0, "Are you trying to kid me?");
00562 DOCHECK(freq > 999999, "Invalid frequency - range is from 0 to 999999.");
00563 notify_printf(player, "Channel %c set to %d.", 'A' + chn, freq);
00564 mech->freq[chn] = freq;
00565
00566
00567
00568
00569
00570
00571 if(freq > 0) {
00572 for(i = 0; i < map->first_free; i++) {
00573 if(!(t = FindObjectsData(map->mechsOnMap[i])))
00574 continue;
00575 if(t == mech)
00576 continue;
00577 if(MechTeam(t) == MechTeam(mech))
00578 continue;
00579 for(j = 0; j < MFreqs(t); j++) {
00580 if(t->freq[j] == freq && !(t->freqmodes[j] & FREQ_SCAN))
00581 SendFreqs(tprintf("ALERT: Possible abuse by #%d (Team %d)"
00582 " setting freq %d matching #%d (Team %d)!",
00583 mech->mynum, MechTeam(mech), freq,
00584 t->mynum, MechTeam(t)));
00585 }
00586 }
00587 }
00588
00589 }
00590
00591 void mech_set_channeltitle(dbref player, void *data, char *buffer)
00592 {
00593 int chn = -1;
00594 MECH *mech = (MECH *) data;
00595
00596 cch(MECH_MAP);
00597 skipws(buffer);
00598 DOCHECK(!*buffer, "Invalid input!");
00599 chn = toupper(*buffer) - 'A';
00600 DOCHECK(chn < 0 || chn >= MFreqs(mech), "Invalid channel-letter!");
00601 buffer++;
00602 skipws(buffer);
00603 DOCHECK(!*buffer, "Invalid input!");
00604 DOCHECK(*buffer != '=', "Missing =!");
00605 buffer++;
00606 skipws(buffer);
00607 if(!*buffer) {
00608 mech->chantitle[chn][0] = 0;
00609 notify_printf(player, "Channel %c title cleared.", 'A' + chn);
00610 return;
00611 }
00612 strncpy(mech->chantitle[chn], buffer, CHTITLELEN);
00613 mech->chantitle[chn][CHTITLELEN] = 0;
00614 notify_printf(player, "Channel %c title set to set to %s.", 'A' + chn,
00615 buffer);
00616 }
00617
00618
00619 const char radio_colorstr[] = "xrgybmcwXRGYBMCW";
00620
00621 static char *ccode(MECH * m, int i, int obs, int team)
00622 {
00623 int t = m->freqmodes[i] / FREQ_REST;
00624 static char buf[6];
00625 int ii;
00626
00627 if(!obs) {
00628 if(!t) {
00629 strcpy(buf, "");
00630 return buf;
00631 };
00632 if(t < 9) {
00633 sprintf(buf, "%%c%c", radio_colorstr[t - 1]);
00634 return buf;
00635 }
00636 sprintf(buf, "%%ch%%c%c", ToLower(radio_colorstr[t - 1]));
00637 } else {
00638 for(ii = 0; ii < 15; ii++) {
00639 if(team == obs_team_color[ii].team)
00640 sprintf(buf, "%s", obs_team_color[ii].ccode);
00641 }
00642 if(buf == NULL)
00643 sprintf(buf, "%s", obs_team_color[0].ccode);
00644 }
00645 return buf;
00646 }
00647
00648 void mech_set_channelmode(dbref player, void *data, char *buffer)
00649 {
00650 int chn = -1, nm = 0, i;
00651 MECH *mech = (MECH *) data;
00652 char buf[SBUF_SIZE];
00653
00654 cch(MECH_MAP);
00655 skipws(buffer);
00656 DOCHECK(!*buffer, "Invalid input!");
00657 chn = toupper(*buffer) - 'A';
00658 DOCHECK(chn < 0 || chn >= MFreqs(mech), "Invalid channel-letter!");
00659 buffer++;
00660 skipws(buffer);
00661 DOCHECK(!*buffer, "Invalid input!");
00662 DOCHECK(*buffer != '=', "Missing =!");
00663 buffer++;
00664 skipws(buffer);
00665 if(!buffer || !*buffer) {
00666 mech->freqmodes[chn] = 0;
00667 notify_printf(player, "Channel %c <send> mode set to analog.",
00668 'A' + chn);
00669 return;
00670 }
00671 while (buffer && *buffer) {
00672 switch (*buffer) {
00673 case 'D':
00674 case 'd':
00675 DOCHECK(MechRadioInfo(mech) & RADIO_NODIGITAL,
00676 "Your radio can't handle digital frequencies!");
00677 nm |= FREQ_DIGITAL;
00678 break;
00679 case 'I':
00680 case 'i':
00681 DOCHECK(!(MechRadioInfo(mech) & RADIO_INFO),
00682 "This unit is unable to use info functionality.");
00683 nm |= FREQ_INFO;
00684 break;
00685 case 'U':
00686 case 'u':
00687 nm |= FREQ_MUTE;
00688 break;
00689 case 'E':
00690 case 'e':
00691 DOCHECK(!(MechRadioInfo(mech) & RADIO_RELAY),
00692 "This unit is unable to relay.");
00693 nm |= FREQ_RELAY;
00694 break;
00695 case 'S':
00696 case 's':
00697 DOCHECK(!(MechRadioInfo(mech) & RADIO_SCAN),
00698 "This unit is unable to scan.");
00699 nm |= FREQ_SCAN;
00700 break;
00701 default:
00702 for(i = 0; radio_colorstr[i]; i++)
00703 if(*buffer == radio_colorstr[i]) {
00704 nm = nm % FREQ_REST + FREQ_REST * (i + 1);
00705 break;
00706 }
00707 if(!radio_colorstr[i])
00708 buffer = NULL;
00709 break;
00710 }
00711 if(buffer)
00712 buffer++;
00713 }
00714 DOCHECK(!(nm & FREQ_DIGITAL) &&
00715 (nm & FREQ_RELAY),
00716 "Error: Need digital transfer for relay to work.");
00717 DOCHECK(!(nm & FREQ_DIGITAL) &&
00718 (nm & FREQ_INFO),
00719 "Error: Need digital transfer for transfer info to work.");
00720 mech->freqmodes[chn] = nm;
00721 i = 0;
00722
00723 if(nm & FREQ_INFO)
00724 buf[i++] = 'I';
00725 if(nm & FREQ_MUTE)
00726 buf[i++] = 'U';
00727 if(nm & FREQ_RELAY)
00728 buf[i++] = 'E';
00729 if(nm & FREQ_SCAN)
00730 buf[i++] = 'S';
00731 if(!i)
00732 buf[i++] = '-';
00733 if(nm / FREQ_REST) {
00734 sprintf(buf + i, "/color:%c", radio_colorstr[nm / FREQ_REST - 1]);
00735 i = strlen(buf);
00736 }
00737 buf[i] = 0;
00738 notify_printf(player, "Channel %c <send> mode set to %s (flags:%s).",
00739 'A' + chn, nm & FREQ_DIGITAL ? "digital" : "analog", buf);
00740 }
00741
00742 void mech_list_freqs(dbref player, void *data, char *buffer)
00743 {
00744 int i;
00745 MECH *mech = (MECH *) data;
00746
00747
00748 notify(player, "# -- Mode -- Frequency -- Comtitle");
00749 for(i = 0; i < MFreqs(mech); i++)
00750 notify_printf(player, "%c %c%c%c%c %-9d %s", 'A' + i,
00751 mech->freqmodes[i] & FREQ_DIGITAL ? 'D' : 'A',
00752 mech->freqmodes[i] & FREQ_RELAY ? 'R' : '-',
00753 mech->freqmodes[i] & FREQ_MUTE ? 'M' : '-',
00754 mech->freqmodes[i] & FREQ_SCAN ? 'S' : mech->
00755 freqmodes[i] >= FREQ_REST ?
00756 radio_colorstr[mech->freqmodes[i] / FREQ_REST - 1] :
00757 mech->freqmodes[i] & FREQ_INFO ? 'I' : '-',
00758 mech->freq[i], mech->chantitle[i]);
00759 }
00760
00761 void mech_sendchannel(dbref player, void *data, char *buffer)
00762 {
00763
00764 MECH *mech = (MECH *) data;
00765 int fail = 0;
00766 int argc;
00767 int chn = 0;
00768 char *args[3];
00769 int i;
00770
00771 cch(MECH_USUALS);
00772 DOCHECK(Destroyed(mech) ||
00773 !MechRadioRange(mech), "Your communication gear is inoperative.");
00774 DOCHECK(CrewStunned(mech), "You are too stunned to use the radio!");
00775 if((argc = proper_parseattributes(buffer, args, 3)) != 3)
00776 fail = 1;
00777 if(!fail && strlen(args[0]) > 1)
00778 fail = 1;
00779 if(!fail && args[0][0] >= 'a' && args[0][0] <= 'z')
00780 chn = args[0][0] - 'a';
00781 if(!fail && args[0][0] >= 'A' && args[0][0] <= 'Z')
00782 chn = args[0][0] - 'Z';
00783 if(!fail && (chn >= MFreqs(mech) || chn < 0))
00784 fail = 1;
00785 if(!fail)
00786 for(i = 0; args[2][i]; i++) {
00787 if((BOUNDED(32, args[2][i], 255)) != args[2][i]) {
00788 notify(player,
00789 "Invalid: No control characters in radio messages, please.");
00790 for(i = 0; i < 3; i++) {
00791 if(args[i])
00792 free(args[i]);
00793 }
00794 return;
00795 }
00796 }
00797
00798 if(fail) {
00799 notify(player,
00800 "Invalid format! Usage: sendchannel <letter>=<string>");
00801 for(i = 0; i < 3; i++) {
00802 if(args[i])
00803 free(args[i]);
00804 }
00805 return;
00806 }
00807
00808 if(mech->freq[chn] == 0 && In_Character(mech->mapindex)) {
00809 send_channel("ZeroFrequencies",
00810 "Player #%d (%s) in mech #%d (channel %c) "
00811 "on map #%d 0-freqs \"%s\"", player, Name(player),
00812 mech->mynum, chn + 'A', mech->mapindex, args[2]);
00813 }
00814
00815 sendchannelstuff(mech, chn, args[2]);
00816 for(i = 0; i < 3; i++) {
00817 if(args[i])
00818 free(args[i]);
00819 }
00820 explode_mines(mech, mech->freq[chn]);
00821 }
00822
00823 #define number(x,y) (rand()%(y-x+1)+x)
00824
00825 static void do_scramble(char *buffo, int ch, int bth)
00826 {
00827 int i;
00828
00829 for(i = 0; buffo[i]; i++) {
00830 if(number(1, 100) > ch && Roll() < (bth + 5)) {
00831 if(number(1, 2) == 1)
00832 buffo[i] -= number(1, 10);
00833 else
00834 buffo[i] += number(1, 10);
00835 }
00836 buffo[i] = (unsigned char) BOUNDED(33, buffo[i], 255);
00837 }
00838 }
00839
00840 #define my_modify(n,fact) (100 - (100 - (n)) / (fact))
00841
00842 static int comm_num_to_conn;
00843 static int comm_is[MAX_MECHS_PER_MAP][MAX_MECHS_PER_MAP];
00844 static int comm_done[MAX_MECHS_PER_MAP];
00845 static MECH *comm_mech[MAX_MECHS_PER_MAP];
00846 static int comm_best;
00847 static int comm_best_path[MAX_MECHS_PER_MAP];
00848 static int comm_path[MAX_MECHS_PER_MAP];
00849
00850 void ScrambleMessage(char *buffo, int range, int sendrange, int recvrrange,
00851 char *handle, char *msg, int bth, int *isxp,
00852 int under_ecm, int digmode)
00853 {
00854
00855 int mr, i;
00856 char *header = NULL;
00857 char buf[LBUF_SIZE];
00858
00859 *isxp = 0;
00860
00861 if(digmode > 1 && comm_best > 1) {
00862 int bearing;
00863
00864 strncpy(buf, "{R-path:", LBUF_SIZE);
00865 for(i = 1; i < comm_best; i++) {
00866 if(i > 1)
00867 strcat(buf, "/");
00868 bearing =
00869 FindBearing(MechFX(comm_mech[comm_best_path[i]]),
00870 MechFY(comm_mech[comm_best_path[i]]),
00871 MechFX(comm_mech[comm_best_path[i - 1]]),
00872 MechFY(comm_mech[comm_best_path[i - 1]]));
00873 snprintf(buf + strlen(buf), LBUF_SIZE, "[%c%c]-h:%.3d",
00874 MechID(comm_mech[comm_best_path[i]])[0],
00875 MechID(comm_mech[comm_best_path[i]])[1], bearing);
00876 }
00877 strcat(buf, "} ");
00878 header = buf;
00879 }
00880
00881 if(handle && *handle)
00882 snprintf(buffo, LBUF_SIZE, "%s<%s> %s", header ? header : "", handle,
00883 msg);
00884 else
00885 snprintf(buffo, LBUF_SIZE, "%s%s", header ? header : "", msg);
00886
00887 if((!digmode && (range >= sendrange || range >= recvrrange)) || under_ecm) {
00888 if(!digmode) {
00889
00890 mr = MAX(recvrrange, (sendrange + recvrrange) / 2);
00891 if(sendrange < range) {
00892 do_scramble(buffo, (100 * sendrange) / MAX(1, range), bth);
00893 *isxp = 1;
00894 }
00895
00896 if(mr < range) {
00897 do_scramble(buffo, my_modify((100 * mr) / MAX(1, range), 2),
00898 bth);
00899 *isxp = 1;
00900 }
00901 }
00902
00903 if(under_ecm && range >= 1) {
00904 do_scramble(buffo, Number(30, 50), bth);
00905 *isxp = 1;
00906 }
00907 }
00908 }
00909
00910 int common_checks(dbref player, MECH * mech, int flag)
00911 {
00912 MAP *mech_map;
00913
00914 if(!mech)
00915 return 0;
00916
00917 if((flag & MECH_CONSISTENT) && !CheckData(player, mech))
00918 return 0;
00919
00920 if(!Wizard(player)) {
00921
00922
00923
00924
00925 if(MechType(mech) == CLASS_AERO)
00926 return 0;
00927
00928 }
00929
00930
00931
00932
00933
00934
00935 MechLastUse(mech) = 0;
00936
00937 if(flag & MECH_STARTED) {
00938 DOCHECK0(Destroyed(mech), "You are destroyed!");
00939 DOCHECK0(!(MechStatus(mech) & STARTED), "Reactor is not online!");
00940 }
00941
00942 if(flag & MECH_PILOT) {
00943 DOCHECK0(Blinded(mech), "You are momentarily blinded!");
00944 }
00945
00946 if(flag & MECH_PILOT_CON)
00947 DOCHECK0(Uncon(mech) && (!Started(mech) ||
00948 player == MechPilot(mech)),
00949 "You are unconscious....zzzzzzz");
00950
00951 if(flag & MECH_PILOTONLY)
00952 DOCHECK0(!Wizard(player) && In_Character(mech->mynum) &&
00953 MechPilot(mech) != player,
00954 "Now now, only the pilot can push that button.");
00955
00956 if(flag & MECH_MAP) {
00957 DOCHECK0(mech->mapindex < 0, "You are on no map!");
00958 mech_map = getMap(mech->mapindex);
00959 if(!mech_map) {
00960 notify(player, "You are on an invalid map! Map index reset!");
00961 mech_shutdown(player, (void *) mech, "");
00962 mech->mapindex = -1;
00963 return 0;
00964 }
00965 }
00966 return 1;
00967 }
00968
00969 static int iter_prevent;
00970
00971 void recursive_commlink(int i, int dep)
00972 {
00973 int j;
00974
00975 if(iter_prevent++ >= 10000)
00976 return;
00977 if(dep >= comm_best)
00978 return;
00979 comm_path[dep] = i;
00980 for(j = 1; j < comm_num_to_conn; j++)
00981 if(comm_is[i][j] && !comm_done[j]) {
00982 if(j == (comm_num_to_conn - 1)) {
00983 int k;
00984
00985 comm_best = dep;
00986 for(k = 0; k < comm_best; k++)
00987 comm_best_path[k] = comm_path[k];
00988 } else {
00989 comm_done[j] = 1;
00990 recursive_commlink(j, dep + 1);
00991 comm_done[j] = 0;
00992 }
00993 }
00994 }
00995
00996 void nonrecursive_commlink(int i)
00997 {
00998 int dep = 0, j;
00999 int comm_loop[MAX_MECHS_PER_MAP];
01000 int iter_c = 0;
01001 int maxdepth = 0;
01002
01003
01004 comm_loop[0] = 1;
01005 comm_path[0] = i;
01006
01007 while (dep >= 0) {
01008 i = comm_path[dep];
01009 for(j = comm_loop[dep]; j < comm_num_to_conn; j++)
01010 if(comm_is[i][j] && !comm_done[j]) {
01011 if(j == (comm_num_to_conn - 1)) {
01012 int k;
01013
01014 comm_best = dep + 1;
01015 for(k = 0; k < comm_best; k++)
01016 comm_best_path[k] = comm_path[k];
01017 j = comm_num_to_conn;
01018 break;
01019 } else if((dep + 1) < comm_best) {
01020 comm_done[j] = 1;
01021 comm_loop[dep++] = j + 1;
01022 comm_loop[dep] = 1;
01023 comm_path[dep] = j;
01024 if(dep > maxdepth)
01025 maxdepth = dep;
01026 break;
01027 }
01028 }
01029 if(j == comm_num_to_conn) {
01030 if(dep > 0)
01031 comm_done[comm_loop[--dep] - 1] = 0;
01032 else
01033 dep--;
01034 }
01035 if(iter_c++ == 100000) {
01036 SendError(tprintf
01037 ("#%d: Infinite loop in relay code (?) ; using backup recursive code (num_mechs:%d, maxdepth:%d, nowdepth:%d)",
01038 comm_mech[0]->mynum, comm_num_to_conn, maxdepth, dep));
01039 comm_best = 9999;
01040 for(i = 0; i < comm_num_to_conn; i++)
01041 comm_done[i] = 0;
01042 iter_prevent = 0;
01043 recursive_commlink(0, 0);
01044 return;
01045 }
01046 }
01047 }
01048
01049 int findCommLink(MAP * map, MECH * from, MECH * to, int freq)
01050 {
01051 int i, j;
01052 MECH *t;
01053
01054 comm_num_to_conn = 0;
01055 comm_mech[comm_num_to_conn++] = from;
01056 for(i = 0; i < map->first_free; i++) {
01057 if(!(t = FindObjectsData(map->mechsOnMap[i])))
01058 continue;
01059 if(t == from || t == to)
01060 continue;
01061 if(MechTeam(from) != MechTeam(t))
01062 continue;
01063 if((MechMove(t) != MOVE_NONE && !Started(t)) ||
01064 (MechMove(t) == MOVE_NONE && Destroyed(t)))
01065 continue;
01066 if(!(MechRadioInfo(t) & RADIO_RELAY))
01067 continue;
01068 for(j = 0; j < MFreqs(t); j++)
01069 if(t->freq[j] == freq)
01070 if(t->freqmodes[j] & FREQ_RELAY) {
01071 comm_mech[comm_num_to_conn++] = t;
01072 continue;
01073 }
01074 }
01075 comm_mech[comm_num_to_conn++] = to;
01076 if(comm_num_to_conn == 2)
01077 return 0;
01078 for(i = 0; i < comm_num_to_conn; i++) {
01079 comm_done[i] = 0;
01080 comm_is[i][i] = 0;
01081 for(j = i + 1; j < comm_num_to_conn; j++) {
01082 float range = FlMechRange(map, comm_mech[i], comm_mech[j]);
01083
01084 comm_is[i][j] = (range <= MechRadioRange(comm_mech[i]));
01085 comm_is[j][i] = (range <= MechRadioRange(comm_mech[j]));
01086 }
01087 }
01088 comm_best = 9999;
01089
01090 nonrecursive_commlink(0);
01091 return comm_best != 9999;
01092 }
01093
01094
01095
01096 void sendchannelstuff(MECH * mech, int freq, char *msg)
01097 {
01098
01099 int loop, range, bearing, i, isxp;
01100 MECH *tempMech;
01101 MAP *mech_map = getMap(mech->mapindex);
01102 char buf[LBUF_SIZE];
01103 char buf2[LBUF_SIZE];
01104 char buf3[LBUF_SIZE];
01105 int sfail_type, sfail_mod;
01106 int rfail_type, rfail_mod;
01107 int obs = 0;
01108
01109 char ai_buf[LBUF_SIZE];
01110
01111
01112
01113
01114 if(!MechRadioRange(mech))
01115 return;
01116
01117
01118 for(loop = 0; loop < mech_map->first_free; loop++) {
01119 if(mech_map->mechsOnMap[loop] != 2) {
01120
01121
01122
01123 if(!
01124 (tempMech =
01125 (MECH *) FindObjectsData(mech_map->mechsOnMap[loop])))
01126 continue;
01127 if(Destroyed(tempMech))
01128 continue;
01129 obs = (MechCritStatus(tempMech) & OBSERVATORIC);
01130 range = FaMechRange(mech, tempMech);
01131 bearing = FindBearing(MechFX(tempMech), MechFY(tempMech),
01132 MechFX(mech), MechFY(mech));
01133 for(i = 0; i < MFreqs(tempMech); i++) {
01134 if(tempMech->freq[i] == mech->freq[freq] || obs) {
01135 if((tempMech->freqmodes[i] & FREQ_MUTE) ||
01136 ((mech->freqmodes[freq] & FREQ_DIGITAL) &&
01137 (MechRadioInfo(tempMech) & RADIO_NODIGITAL)))
01138 continue;
01139 break;
01140 }
01141 }
01142 if(i >= MFreqs(tempMech)) {
01143
01144 if(!(mech->freqmodes[freq] & FREQ_DIGITAL))
01145 if((MechRadioInfo(tempMech) & RADIO_SCAN) &&
01146 mech->freq[freq]) {
01147 int tnc = 0;
01148
01149 for(i = 0; i < MFreqs(tempMech); i++)
01150 if(tempMech->freqmodes[i] & FREQ_SCAN) {
01151 int l = strlen(msg), t;
01152 int mod, diff;
01153 int pr;
01154
01155
01156
01157
01158 if(Number(1, 100) > MIN(80, l))
01159 continue;
01160
01161 if(!tnc++)
01162 mech_notify(tempMech, MECHALL,
01163 "You notice a "
01164 "unknown transmission your scanner.. ");
01165 if(tempMech->freq[i] < mech->freq[freq]) {
01166 diff =
01167 mech->freq[freq] - tempMech->freq[i];
01168 mod = 1;
01169 } else {
01170 diff =
01171 tempMech->freq[i] - mech->freq[freq];
01172 mod = -1;
01173 }
01174
01175 t = MAX(1,
01176 Number(1, MIN(99, l)) * diff / 100);
01177 pr = t * 100 / diff;
01178 mech_printf(tempMech, MECHALL, "Your systems "
01179 "manage to zero on it %s on channel %c.",
01180 pr < 30 ? "somewhat" : pr < 60 ?
01181 "fairly well" : pr < 95 ?
01182 "precisely" : "exactly", i + 'A');
01183 tempMech->freq[i] += mod * t;
01184 }
01185
01186 }
01187
01188 continue;
01189
01190 }
01191
01192 strncpy(buf2, msg, LBUF_SIZE);
01193
01194
01195
01196
01197
01198 if(obs) {
01199 if(mech->freqmodes[freq] & FREQ_DIGITAL) {
01200 snprintf(buf, LBUF_SIZE, "%s[%c:%d] <%s:%s:%d> <%s> %s%%c",
01201 ccode(tempMech, i, obs, MechTeam(mech)),
01202 (char) ('A' + i), bearing,
01203 silly_atr_get(mech->mynum, A_FACTION),
01204 MechIDS(mech, 0), mech->freq[freq], mech->chantitle[freq],buf2);
01205 } else {
01206 snprintf(buf, LBUF_SIZE, "%s(%c:%d) <%s:%s:%d> <%s> %s%%c",
01207 ccode(tempMech, i, obs, MechTeam(mech)),
01208 (char) ('A' + i), bearing,
01209 silly_atr_get(mech->mynum, A_FACTION),
01210 MechIDS(mech, 0), mech->freq[freq], mech->chantitle[freq],buf2);
01211 }
01212 mech_notify(tempMech, MECHALL, buf);
01213 }
01214
01215
01216
01217 if(MechAuto(tempMech) > 0 && tempMech->freq[i]) {
01218 AUTO *a = (AUTO *) FindObjectsData(MechAuto(tempMech));
01219
01220
01221 if(!a) {
01222
01223 MechAuto(tempMech) = -1;
01224 } else if(a && Location(a->mynum) != tempMech->mynum) {
01225
01226 snprintf(ai_buf, LBUF_SIZE,
01227 "Autopilot #%d (Location: #%d) "
01228 "reported on Mech #%d but not in the proper location",
01229 a->mynum, Location(a->mynum), tempMech->mynum);
01230 SendAI(ai_buf);
01231 } else if(a && !ECMDisturbed(tempMech)) {
01232
01233 strncpy(buf3, msg, LBUF_SIZE);
01234 auto_parse_command(a, tempMech, i, buf3);
01235 }
01236 }
01237
01238
01239
01240 if(!MechRadioRange(tempMech))
01241 continue;
01242 if(mech->freqmodes[freq] & FREQ_DIGITAL) {
01243 if(range > MechRadioRange(mech)) {
01244 if(!findCommLink
01245 (mech_map, mech, tempMech, mech->freq[freq]))
01246 continue;
01247 } else
01248 comm_best = 1;
01249
01250 if(tempMech != mech) {
01251 if(AnyECMDisturbed(mech))
01252 continue;
01253 else if(AnyECMDisturbed(tempMech))
01254 continue;
01255 }
01256
01257 ScrambleMessage(buf3, range, MechRadioRange(mech),
01258 MechRadioRange(mech), mech->chantitle[freq],
01259 buf2, MechComm(tempMech), &isxp, 0,
01260 (tempMech->freqmodes[i] & FREQ_INFO) ? 2 : 1);
01261
01262 if(comm_best >= 2)
01263 bearing = FindBearing(MechFX(tempMech), MechFY(tempMech),
01264 MechFX(comm_mech
01265 [comm_best_path
01266 [comm_best - 1]]),
01267 MechFY(comm_mech
01268 [comm_best_path
01269 [comm_best - 1]]));
01270 if(!obs)
01271 snprintf(buf, LBUF_SIZE, "%s[%c:%.3d] %s%%c",
01272 ccode(tempMech, i, obs, MechTeam(mech)),
01273 (char) ('A' + i), bearing, buf3);
01274
01275 } else {
01276
01277 ScrambleMessage(buf3, range, MechRadioRange(mech),
01278 MechRadioRange(tempMech),
01279 mech->chantitle[freq], buf2,
01280 MechComm(tempMech), &isxp,
01281 (AnyECMDisturbed(mech)
01282 || AnyECMDisturbed(tempMech)
01283
01284
01285
01286
01287 ) && mech != tempMech, 0);
01288 if(!obs)
01289 snprintf(buf, LBUF_SIZE, "%s(%c:%.3d) %s%%c",
01290 ccode(tempMech, i, obs, MechTeam(mech)),
01291 (char) ('A' + i), bearing, buf3);
01292
01293 }
01294
01295 if(!obs)
01296 mech_notify(tempMech, MECHALL, buf);
01297 if(isxp && In_Character(tempMech->mynum))
01298 if((MechCommLast(tempMech) + 60) < muxevent_tick) {
01299 AccumulateCommXP(MechPilot(tempMech), tempMech);
01300 MechCommLast(tempMech) = muxevent_tick;
01301 }
01302
01303 }
01304 }
01305 }
01306
01307 void mech_radio(dbref player, void *data, char *buffer)
01308 {
01309 int argc;
01310 int fail = 0;
01311 char *args[3];
01312 int i;
01313 MECH *mech = (MECH *) data;
01314 dbref target;
01315 MECH *tempMech;
01316
01317
01318
01319
01320 cch(MECH_USUAL);
01321
01322 DOCHECK(MechIsObservator(mech), "You can't radio anyone.");
01323 if((argc = proper_parseattributes(buffer, args, 3)) != 3)
01324 fail = 1;
01325 if(!fail && (!args[1] || args[1][0] != '=' || args[1][1] != 0))
01326 fail = 1;
01327 if(!fail && (!args[0] || args[0][0] == 0 || args[0][1] == 0 ||
01328 args[0][2] != 0))
01329 fail = 1;
01330 if(!fail) {
01331 target = FindTargetDBREFFromMapNumber(mech, args[0]);
01332 tempMech = getMech(target);
01333 DOCHECK(!tempMech ||
01334 !InLineOfSight(mech, tempMech, MechX(tempMech),
01335 MechY(tempMech), FlMechRange(map, mech,
01336 tempMech)),
01337 "Target is not in line of sight!");
01338 mech_printf(mech, MECHSTARTED, "You radio %s with, '%s'",
01339 GetMechToMechID(mech, tempMech), args[2]);
01340 mech_printf(tempMech, MECHSTARTED, "%s radios you with, '%s'",
01341 GetMechToMechID(tempMech, mech), args[2]);
01342 auto_reply(tempMech,
01343 tprintf("%s radio'ed me '%s'",
01344 GetMechToMechID(tempMech, mech), args[2]));
01345 }
01346 DOCHECK(fail, "Invalid format! Usage: radio <letter><letter>=<message>");
01347 for(i = 0; i < 3; i++) {
01348 if(args[i])
01349 free(args[i]);
01350 }
01351 }
01352
01353 int MapLimitedBroadcast2d(MAP * map, float x, float y, float range,
01354 char *message)
01355 {
01356 int loop, count = 0;
01357 MECH *mech;
01358
01359 for(loop = 0; loop < map->first_free; loop++) {
01360 if(map->mechsOnMap[loop] < 0)
01361 continue;
01362 mech = getMech(map->mechsOnMap[loop]);
01363
01364 if(mech && FindXYRange(x, y, MechFX(mech), MechFY(mech)) <= range) {
01365 mech_notify(mech, MECHSTARTED, message);
01366 count++;
01367 }
01368 }
01369 return count;
01370 }
01371
01372 int MapLimitedBroadcast3d(MAP * map, float x, float y, float z, float range,
01373 char *message)
01374 {
01375 int loop, count = 0;
01376 MECH *mech;
01377
01378 for(loop = 0; loop < map->first_free; loop++) {
01379 if(map->mechsOnMap[loop] == -1)
01380 continue;
01381 mech = getMech(map->mechsOnMap[loop]);
01382 if(mech
01383 && FindRange(x, y, z, MechFX(mech), MechFY(mech),
01384 MechFZ(mech)) <= range) {
01385 count++;
01386 mech_notify(mech, MECHSTARTED, message);
01387 }
01388 }
01389 return count;
01390 }
01391
01392 void MechBroadcast(MECH * mech, MECH * target, MAP * mech_map, char *buffer)
01393 {
01394 int loop;
01395 MECH *tempMech;
01396
01397 if(target) {
01398 for(loop = 0; loop < mech_map->first_free; loop++) {
01399 if(mech_map->mechsOnMap[loop] != mech->mynum &&
01400 mech_map->mechsOnMap[loop] != -1 &&
01401 mech_map->mechsOnMap[loop] != target->mynum) {
01402 tempMech = (MECH *)
01403 FindObjectsData(mech_map->mechsOnMap[loop]);
01404 if(tempMech)
01405 mech_notify(tempMech, MECHSTARTED, buffer);
01406 }
01407 }
01408 } else {
01409 for(loop = 0; loop < mech_map->first_free; loop++) {
01410 if(mech_map->mechsOnMap[loop] != mech->mynum &&
01411 mech_map->mechsOnMap[loop] != -1) {
01412 tempMech = (MECH *)
01413 FindObjectsData(mech_map->mechsOnMap[loop]);
01414 if(tempMech)
01415 mech_notify(tempMech, MECHSTARTED, buffer);
01416 }
01417 }
01418 }
01419 }
01420
01421 void MechLOSBroadcast(MECH * mech, char *message)
01422 {
01423
01424 int i;
01425 MECH *tempMech;
01426 MAP *mech_map = getMap(mech->mapindex);
01427 char buf[LBUF_SIZE];
01428
01429 possibly_see_mech(mech);
01430 if(!mech_map)
01431 return;
01432 for(i = 0; i < mech_map->first_free; i++)
01433 if(mech_map->mechsOnMap[i] != -1 &&
01434 mech_map->mechsOnMap[i] != mech->mynum)
01435 if((tempMech = getMech(mech_map->mechsOnMap[i])))
01436 if(InLineOfSight(tempMech, mech, MechX(mech), MechY(mech),
01437 FlMechRange(mech_map, tempMech, mech))) {
01438 sprintf(buf, "%s%s%s", GetMechToMechID(tempMech, mech),
01439 *message != '\'' ? " " : "", message);
01440 mech_notify(tempMech, MECHSTARTED, buf);
01441 }
01442 }
01443
01444 int MechSeesHexF(MECH * mech, MAP * map, float x, float y, int ix, int iy)
01445 {
01446 return (InLineOfSight(mech, NULL, ix, iy, FindRange(MechFX(mech),
01447 MechFY(mech),
01448 MechFZ(mech), x, y,
01449 ZSCALE *
01450 Elevation(map, ix,
01451 iy))));
01452 }
01453
01454 int MechSeesHex(MECH * mech, MAP * map, int x, int y)
01455 {
01456 float fx, fy;
01457
01458 MapCoordToRealCoord(x, y, &fx, &fy);
01459 return MechSeesHexF(mech, map, fx, fy, x, y);
01460 }
01461
01462 void HexLOSBroadcast(MAP * mech_map, int x, int y, char *message)
01463 {
01464 int i;
01465 MECH *tempMech;
01466 float fx, fy;
01467
01468
01469
01470
01471
01472 if(!mech_map)
01473 return;
01474 MapCoordToRealCoord(x, y, &fx, &fy);
01475 for(i = 0; i < mech_map->first_free; i++)
01476 if(mech_map->mechsOnMap[i] != -1)
01477 if((tempMech = getMech(mech_map->mechsOnMap[i])))
01478 if(MechSeesHexF(tempMech, mech_map, fx, fy, x, y)) {
01479 char tbuf[LBUF_SIZE];
01480 char *c, *d = tbuf;
01481 int done;
01482
01483 for(c = message; *c; c++) {
01484 done = 0;
01485 if(*c == '$') {
01486 if(*(c + 1) == 'h' || *(c + 1) == 'H') {
01487 c++;
01488 if(*c == 'h') {
01489 if(x == MechX(tempMech) &&
01490 y == MechY(tempMech))
01491 strcpy(d, "your hex");
01492 else
01493 sprintf(d, "%d,%d", x, y);
01494 while (*d)
01495 d++;
01496 } else {
01497
01498 if(x == MechX(tempMech) &&
01499 y == MechY(tempMech))
01500 strcpy(d, "%ch%crYOUR HEX%cn");
01501 else
01502 sprintf(d, "%%ch%%cy%d,%d%%cn", x, y);
01503 while (*d)
01504 d++;
01505 }
01506 done = 1;
01507 }
01508 }
01509 if(!done)
01510 *(d++) = *c;
01511 }
01512
01513 if(*(d - 1) == '$')
01514 d--;
01515 *d = '\0';
01516 mech_notify(tempMech, MECHSTARTED, tbuf);
01517 }
01518 }
01519
01520 void MechLOSBroadcasti(MECH * mech, MECH * target, char *message)
01521 {
01522
01523 int i, a, b;
01524 char oddbuff[LBUF_SIZE];
01525 char oddbuff2[LBUF_SIZE];
01526 MECH *tempMech;
01527 MAP *mech_map = getMap(mech->mapindex);
01528
01529 if(!mech_map)
01530 return;
01531 possibly_see_mech(mech);
01532 possibly_see_mech(target);
01533 for(i = 0; i < mech_map->first_free; i++)
01534 if(mech_map->mechsOnMap[i] != -1 &&
01535 mech_map->mechsOnMap[i] != mech->mynum &&
01536 mech_map->mechsOnMap[i] != target->mynum)
01537 if((tempMech = getMech(mech_map->mechsOnMap[i]))) {
01538 a = InLineOfSight(tempMech, mech, MechX(mech), MechY(mech),
01539 FlMechRange(mech_map, tempMech, mech));
01540 b = InLineOfSight(tempMech, target, MechX(target),
01541 MechY(target), FlMechRange(mech_map,
01542 tempMech,
01543 target));
01544 if(a || b) {
01545 sprintf(oddbuff, message, b ? GetMechToMechID(tempMech,
01546 target) :
01547 "someone");
01548 sprintf(oddbuff2, "%s%s%s",
01549 a ? GetMechToMechID(tempMech, mech) : "Someone",
01550 *oddbuff != '\'' ? " " : "", oddbuff);
01551 mech_notify(tempMech, MECHSTARTED, oddbuff2);
01552 }
01553 }
01554 }
01555
01556 void MapBroadcast(MAP * map, char *message)
01557 {
01558
01559 int i;
01560 MECH *tempMech;
01561
01562 for(i = 0; i < map->first_free; i++)
01563 if(map->mechsOnMap[i] != -1)
01564 if((tempMech = getMech(map->mechsOnMap[i])))
01565 mech_notify(tempMech, MECHSTARTED, message);
01566 }
01567
01568 void MechFireBroadcast(MECH * mech, MECH * target, int x, int y,
01569 MAP * mech_map, char *weapname, int IsHit)
01570 {
01571 int loop, attacker, defender;
01572 float fx, fy, fz;
01573 int mapx, mapy;
01574 MECH *tempMech;
01575 char buff[50];
01576
01577 possibly_see_mech(mech);
01578 if(target) {
01579 possibly_see_mech(target);
01580 mapx = MechX(target);
01581 mapy = MechY(target);
01582 fx = MechFX(target);
01583 fy = MechFY(target);
01584 fz = MechFZ(target);
01585 for(loop = 0; loop < mech_map->first_free; loop++)
01586 if(mech_map->mechsOnMap[loop] != mech->mynum &&
01587 mech_map->mechsOnMap[loop] != -1 &&
01588 mech_map->mechsOnMap[loop] != target->mynum) {
01589 attacker = 0;
01590 defender = 0;
01591 tempMech = (MECH *)
01592 FindObjectsData(mech_map->mechsOnMap[loop]);
01593 if(!tempMech)
01594 continue;
01595 if(InLineOfSight(tempMech, mech, MechX(mech), MechY(mech),
01596 FlMechRange(mech_map, tempMech, mech)))
01597 attacker = 1;
01598 if(target) {
01599 if(InLineOfSight(tempMech, target, mapx, mapy,
01600 FlMechRange(mech_map, tempMech, target)))
01601 defender = 1;
01602 } else if(InLineOfSight(tempMech, target, mapx, mapy,
01603 FindRange(MechFX(tempMech),
01604 MechFY(tempMech),
01605 MechFZ(tempMech), fx, fy,
01606 fz)))
01607 defender = 1;
01608
01609 if(!attacker && !defender)
01610 continue;
01611 if(defender)
01612 sprintf(buff, "%s", GetMechToMechID(tempMech, target));
01613 if(attacker) {
01614 if(defender)
01615 mech_printf(tempMech, MECHSTARTED,
01616 "%s %s %s with a %s",
01617 GetMechToMechID(tempMech, mech),
01618 IsHit ? "hits" : "misses", buff,
01619 weapname);
01620 else
01621 mech_printf(tempMech, MECHSTARTED,
01622 "%s fires a %s at something!",
01623 GetMechToMechID(tempMech, mech),
01624 weapname);
01625 } else
01626 mech_printf(tempMech, MECHSTARTED,
01627 "Something %s %s with a %s",
01628 IsHit ? "hits" : "misses", buff, weapname);
01629 }
01630 } else {
01631 mapx = x;
01632 mapy = y;
01633 MapCoordToRealCoord(x, y, &fx, &fy);
01634 fz = ZSCALE * Elevation(mech_map, x, y);
01635 sprintf(buff, "hex %d %d!", mapx, mapy);
01636 for(loop = 0; loop < mech_map->first_free; loop++)
01637 if(mech_map->mechsOnMap[loop] != mech->mynum &&
01638 mech_map->mechsOnMap[loop] != -1) {
01639 attacker = 0;
01640 defender = 0;
01641 tempMech = (MECH *)
01642 FindObjectsData(mech_map->mechsOnMap[loop]);
01643 if(!tempMech)
01644 continue;
01645 if(InLineOfSight(tempMech, mech, MechX(mech), MechY(mech),
01646 FlMechRange(mech_map, tempMech, mech)))
01647 attacker = 1;
01648 if(target) {
01649 if(InLineOfSight(tempMech, target, mapx, mapy,
01650 FlMechRange(mech_map, tempMech, target)))
01651 defender = 1;
01652 } else if(InLineOfSight(tempMech, target, mapx, mapy,
01653 FindRange(MechFX(tempMech),
01654 MechFY(tempMech),
01655 MechFZ(tempMech), fx, fy,
01656 fz)))
01657 defender = 1;
01658 if(!attacker && !defender)
01659 continue;
01660 if(attacker) {
01661 if(defender)
01662 mech_printf(tempMech, MECHSTARTED,
01663 "%s fires a %s at %s",
01664 GetMechToMechID(tempMech, mech), weapname,
01665 buff);
01666 else
01667 mech_printf(tempMech, MECHSTARTED,
01668 "%s fires a %s at something!",
01669 GetMechToMechID(tempMech, mech),
01670 weapname);
01671 } else
01672 mech_printf(tempMech, MECHSTARTED,
01673 "Something fires a %s at %s", weapname, buff);
01674 }
01675 }
01676 }
01677
01678 extern int arc_override;
01679
01680 void mech_notify(MECH * mech, int type, char *buffer)
01681 {
01682 int i;
01683
01684 if(Uncon(mech))
01685 return;
01686 if(Blinded(mech))
01687 return;
01688 if(mech->mynum < 0)
01689 return;
01690
01691
01692 if(type == MECHPILOT) {
01693 if(GotPilot(mech))
01694 notify(MechPilot(mech), buffer);
01695 else
01696 mech_notify(mech, MECHALL, buffer);
01697 } else if((type == MECHALL && !Destroyed(mech)) ||
01698 (type == MECHSTARTED && Started(mech))) {
01699 notify_except(mech->mynum, NOSLAVE, mech->mynum, buffer);
01700 if(arc_override)
01701 for(i = 0; i < NUM_TURRETS; i++)
01702 if(AeroTurret(mech, i) > 0)
01703 notify_except(AeroTurret(mech, i), NOSLAVE,
01704 AeroTurret(mech, i), buffer);
01705 }
01706 }
01707
01708 void mech_printf(MECH * mech, int type, char *format, ...)
01709 {
01710 char buffer[LBUF_SIZE];
01711 int i;
01712 va_list ap;
01713
01714 if(Uncon(mech))
01715 return;
01716 if(Blinded(mech))
01717 return;
01718 if(mech->mynum < 0)
01719 return;
01720
01721
01722 va_start(ap, format);
01723 vsnprintf(buffer, LBUF_SIZE, format, ap);
01724 va_end(ap);
01725
01726 if(type == MECHPILOT) {
01727 if(GotPilot(mech))
01728 notify(MechPilot(mech), buffer);
01729 else
01730 mech_notify(mech, MECHALL, buffer);
01731 } else if((type == MECHALL && !Destroyed(mech)) ||
01732 (type == MECHSTARTED && Started(mech))) {
01733 notify_except(mech->mynum, NOSLAVE, mech->mynum, buffer);
01734 if(arc_override)
01735 for(i = 0; i < NUM_TURRETS; i++)
01736 if(AeroTurret(mech, i) > 0)
01737 notify_except(AeroTurret(mech, i), NOSLAVE,
01738 AeroTurret(mech, i), buffer);
01739 }
01740 }