/* * $Id: mech.c3.misc.c,v 1.1.1.1 2005/01/11 21:18:12 kstevens Exp $ * * Author: Cord Awtry <kipsta@mediaone.net> * Copyright (c) 2000-2002 Cord Awtry * All rights reserved * * Based on work that was: * Copyright (c) 1997 Markus Stenberg * Copyright (c) 1998-2000 Thomas Wouters */ #include "mech.h" #include "p.mech.c3.misc.h" #include "p.mech.c3.h" #include "p.mech.c3i.h" #include "p.mech.utils.h" #include "p.mech.los.h" #include "p.mech.contacts.h" #define TARG_LOS_NONE 0 #define TARG_LOS_CLEAR 1 #define TARG_LOS_SOMETHING 2 #define DEBUG_C3 0 MECH *getMechInTempNetwork(int wIdx, dbref * myNetwork, int networkSize) { MECH *tempMech; dbref refOtherMech; if ((wIdx > networkSize) || (wIdx < 0)) return NULL; refOtherMech = myNetwork[wIdx]; if (refOtherMech > 0) { tempMech = getMech(refOtherMech); if (!tempMech) return NULL; if (Destroyed(tempMech)) return NULL; return tempMech; } return NULL; } MECH *getOtherMechInNetwork(MECH * mech, int wIdx, int tCheckECM, int tCheckStarted, int tCheckUncon, int tIsC3) { MECH *tempMech; dbref refOtherMech; int networkSize; networkSize = (tIsC3 ? MechC3NetworkSize(mech) : MechC3iNetworkSize(mech)); if ((wIdx >= networkSize) || (wIdx < 0)) return NULL; refOtherMech = (tIsC3 ? MechC3NetworkElem(mech, wIdx) : MechC3iNetworkElem(mech, wIdx)); if (refOtherMech > 0) { tempMech = getMech(refOtherMech); if (!tempMech) return NULL; if (MechTeam(tempMech) != MechTeam(mech)) return NULL; if (tempMech->mapindex != mech->mapindex) return NULL; if (Destroyed(tempMech)) return NULL; if (tIsC3) { if (!HasC3(tempMech)) /* Sanity check */ return NULL; if (C3Destroyed(tempMech)) return NULL; } else { if (!HasC3i(tempMech)) /* Sanity check */ return NULL; if (C3iDestroyed(tempMech)) return NULL; } if (tCheckECM) if (AnyECMDisturbed(tempMech)) return NULL; if (tCheckStarted) if (!Started(tempMech)) return NULL; if (tCheckUncon) if (Uncon(tempMech)) return NULL; return tempMech; } return NULL; } void buildTempNetwork(MECH * mech, dbref * myNetwork, int *networkSize, int tCheckECM, int tCheckStarted, int tCheckUncon, int tIsC3) { int tempNetworkSize = 0; int baseNetworkSize; MECH *otherMech; dbref myTempNetwork[C3_NETWORK_SIZE]; int i; /* Re-init the network */ for (i = 0; i < C3_NETWORK_SIZE; i++) myNetwork[i] = -1; *networkSize = 0; baseNetworkSize = (tIsC3 ? MechC3NetworkSize(mech) : MechC3iNetworkSize(mech)); if (baseNetworkSize == 0) return; /* * Build the base netork of all the mechs that fit the criteria we passed in */ for (i = 0; i < baseNetworkSize; i++) { otherMech = getOtherMechInNetwork(mech, i, tCheckECM, tCheckStarted, tCheckUncon, tIsC3); if (!otherMech) continue; if (!Good_obj(otherMech->mynum)) continue; myTempNetwork[tempNetworkSize] = otherMech->mynum; tempNetworkSize++; } /* * Once we're here, we're done with the C3i stuff, but we need to make sure that this is a valid C3 network * still. For example, we may have lost a master due to death or something else, so we need to make sure we * have enough masters left to actually do something. * * A valid network is one where there are MIN((((NUM_MASTERS * 4) - NUM_MASTERS) + ((MY_MASTERS * 4) - MY_MASTERS), 11) units in the network */ if (tIsC3) { if (tempNetworkSize > 0) tempNetworkSize = trimC3Network(mech, myTempNetwork, tempNetworkSize); } for (i = 0; i < tempNetworkSize; i++) myNetwork[i] = myTempNetwork[i]; *networkSize = tempNetworkSize; } void sendNetworkMessage(dbref player, MECH * mech, char *msg, int tIsC3) { int i; MECH *otherMech; const char *c = GetMechID(mech); char buf[LBUF_SIZE]; int networkSize; dbref myNetwork[C3_NETWORK_SIZE]; buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 1, tIsC3); for (i = 0; i < networkSize; i++) { otherMech = getMechInTempNetwork(i, myNetwork, networkSize); if (!otherMech) continue; if (!Good_obj(otherMech->mynum)) continue; sprintf(buf, "%%ch%s/%s: %s%%cn", (tIsC3 ? "C3" : "C3i"), c, msg); mech_notify(otherMech, MECHALL, buf); } sprintf(buf, "%%ch%s/You: %s%%cn", (tIsC3 ? "C3" : "C3i"), msg); mech_notify(mech, MECHALL, buf); } void showNetworkTargets(dbref player, MECH * mech, int tIsC3) { MAP *objMap = getMap(mech->mapindex); int i, j, wTemp, bearing; MECH *otherMech; float realRange, c3Range; char buff[100]; char *mech_name; char move_type[30]; char cStatus1, cStatus2, cStatus3, cStatus4, cStatus5; char weaponarc; int losFlag; int arc; int wSeeTarget = TARG_LOS_NONE; int wC3SeeTarget = TARG_LOS_NONE; int tShowStatusInfo = 0; char bufflist[MAX_MECHS_PER_MAP][120]; float rangelist[MAX_MECHS_PER_MAP]; int buffindex = 0; int sbuff[MAX_MECHS_PER_MAP]; int networkSize; dbref myNetwork[C3_NETWORK_SIZE]; dbref c3Ref; buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3); /* * Send then a 'contacts' style report. This is different from the * normal contacts since it has a 'physical' range in it too. */ notify(player, tprintf("%s Contacts:", tIsC3 ? "C3" : "C3i")); for (i = 0; i < objMap->first_free; i++) { if (!(objMap->mechsOnMap[i] != mech->mynum && objMap->mechsOnMap[i] != -1)) continue; otherMech = (MECH *) FindObjectsData(objMap->mechsOnMap[i]); if (!otherMech) continue; if (!Good_obj(otherMech->mynum)) continue; tShowStatusInfo = 0; realRange = FlMechRange(objMap, mech, otherMech); losFlag = InLineOfSight(mech, otherMech, MechX(otherMech), MechY(otherMech), realRange); /* * If we do see them, let's make sure it's not just a 'something' */ if (losFlag) { if (InLineOfSight_NB(mech, otherMech, MechX(otherMech), MechY(otherMech), 0.0)) wSeeTarget = TARG_LOS_CLEAR; else wSeeTarget = TARG_LOS_SOMETHING; } else wSeeTarget = TARG_LOS_NONE; /* * If I don't see it, let's see if someone else in the network does */ if (wSeeTarget != TARG_LOS_CLEAR) wC3SeeTarget = mechSeenByNetwork(mech, otherMech, tIsC3); /* If noone sees it, we continue */ if (!wSeeTarget && !wC3SeeTarget) continue; /* Get our network range */ c3Range = findC3RangeWithNetwork(mech, otherMech, realRange, myNetwork, networkSize, &c3Ref); /* Figure out if we show the info or not... ie, do we actually 'see' it */ if ((wSeeTarget != TARG_LOS_CLEAR) && (wC3SeeTarget != TARG_LOS_CLEAR)) { tShowStatusInfo = 0; mech_name = "something"; } else { tShowStatusInfo = 1; mech_name = silly_atr_get(otherMech->mynum, A_MECHNAME); } bearing = FindBearing(MechFX(mech), MechFY(mech), MechFX(otherMech), MechFY(otherMech)); strcpy(move_type, GetMoveTypeID(MechMove(otherMech))); /* Get our weapon arc */ arc = InWeaponArc(mech, MechFX(otherMech), MechFY(otherMech)); weaponarc = getWeaponArc(mech, arc); /* Now get our status chars */ if (!tShowStatusInfo) { cStatus1 = ' '; cStatus2 = ' '; cStatus3 = ' '; cStatus4 = ' '; cStatus5 = ' '; } else { cStatus1 = getStatusChar(mech, otherMech, 1); cStatus2 = getStatusChar(mech, otherMech, 2); cStatus3 = getStatusChar(mech, otherMech, 3); cStatus4 = getStatusChar(mech, otherMech, 4); cStatus5 = getStatusChar(mech, otherMech, 5); } /* Now, build the string */ sprintf(buff, "%s%c%c%c[%s]%c %-11.11s x:%3d y:%3d z:%3d r:%4.1f c:%4.1f b:%3d s:%5.1f h:%3d S:%c%c%c%c%c%s", otherMech->mynum == MechTarget(mech) ? "%ch%cr" : (tShowStatusInfo && !MechSeemsFriend(mech, otherMech)) ? "%ch%cy" : "", (losFlag & MECHLOSFLAG_SEESP) ? 'P' : ' ', (losFlag & MECHLOSFLAG_SEESS) ? 'S' : ' ', weaponarc, MechIDS(otherMech, MechSeemsFriend(mech, otherMech) || !tShowStatusInfo), move_type[0], mech_name, MechX(otherMech), MechY(otherMech), MechZ(otherMech), realRange, c3Range, bearing, MechSpeed(otherMech), MechVFacing(otherMech), cStatus1, cStatus2, cStatus3, cStatus4, cStatus5, (otherMech->mynum == MechTarget(mech) || !MechSeemsFriend(mech, otherMech)) ? "%c" : ""); rangelist[buffindex] = realRange; rangelist[buffindex] += (MechStatus(otherMech) & DESTROYED) ? 10000 : 0; strcpy(bufflist[buffindex++], buff); } for (i = 0; i < buffindex; i++) sbuff[i] = i; /* print a sorted list of detected mechs */ /* use the ever-popular bubble sort */ for (i = 0; i < (buffindex - 1); i++) for (j = (i + 1); j < buffindex; j++) if (rangelist[sbuff[j]] > rangelist[sbuff[i]]) { wTemp = sbuff[i]; sbuff[i] = sbuff[j]; sbuff[j] = wTemp; } for (i = 0; i < buffindex; i++) notify(player, bufflist[sbuff[i]]); notify(player, tprintf("End %s Contact List", tIsC3 ? "C3" : "C3i")); } void showNetworkData(dbref player, MECH * mech, int tIsC3) { int i, bearing; MECH *otherMech; float range; char buff[100]; char *mech_name; char move_type[30]; int networkSize; dbref myNetwork[C3_NETWORK_SIZE]; notify(player, tprintf("%s Network Status:", tIsC3 ? "C3" : "C3i")); buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3); for (i = 0; i < networkSize; i++) { otherMech = getMechInTempNetwork(i, myNetwork, networkSize); if (!otherMech) continue; if (!Good_obj(otherMech->mynum)) continue; range = FlMechRange(objMap, mech, otherMech); bearing = FindBearing(MechFX(mech), MechFY(mech), MechFX(otherMech), MechFY(otherMech)); strcpy(move_type, GetMoveTypeID(MechMove(otherMech))); mech_name = silly_atr_get(otherMech->mynum, A_MECHNAME); sprintf(buff, "%%ch%%cy[%s]%c %-12.12s x:%3d y:%3d z:%3d r:%4.1f b:%3d s:%5.1f h:%3d a: %3d i: %3d%%cn", MechIDS(otherMech, 1), move_type[0], mech_name, MechX(otherMech), MechY(otherMech), MechZ(otherMech), range, bearing, MechSpeed(otherMech), MechVFacing(otherMech), getRemainingArmorPercent(otherMech), getRemainingInternalPercent(otherMech)); notify(player, buff); } notify(player, tprintf("End %s Network Status", tIsC3 ? "C3" : "C3i")); } int mechSeenByNetwork(MECH * mech, MECH * mechTarget, int tIsC3) { int los = TARG_LOS_NONE; float range = 0.0; int i; int networkSize; dbref myNetwork[C3_NETWORK_SIZE]; MECH *otherMech; buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3); if (networkSize == 0) return TARG_LOS_NONE; for (i = 0; i < networkSize; i++) { otherMech = getMechInTempNetwork(i, myNetwork, networkSize); if (!otherMech) continue; if (!Good_obj(otherMech->mynum)) continue; if (otherMech == mechTarget) continue; range = FaMechRange(otherMech, mechTarget); los = InLineOfSight(otherMech, mechTarget, MechX(mechTarget), MechY(mechTarget), range); if (los) { if (!InLineOfSight_NB(otherMech, mechTarget, MechX(mechTarget), MechY(mechTarget), range)) los = TARG_LOS_SOMETHING; else { los = TARG_LOS_CLEAR; break; } } } return los; } float findC3Range(MECH * mech, MECH * mechTarget, float realRange, dbref * c3Ref, int tIsC3) { int networkSize; dbref myNetwork[C3_NETWORK_SIZE]; if (tIsC3) { if (C3Destroyed(mech)) { return realRange; } } else { if (C3iDestroyed(mech)) { validateC3iNetwork(mech); return realRange; } } if (AnyECMDisturbed(mech)) return realRange; buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3); return findC3RangeWithNetwork(mech, mechTarget, realRange, myNetwork, networkSize, c3Ref); } float findC3RangeWithNetwork(MECH * mech, MECH * mechTarget, float realRange, dbref * myNetwork, int networkSize, dbref * c3Ref) { float c3Range = 0.0; float bestRange = 0.0; int i; int inLOS = 0; int mapX, mapY; float hexX, hexY, hexZ; MECH *otherMech; MAP *map; bestRange = realRange; *c3Ref = 0; if (networkSize == 0) return realRange; for (i = 0; i < networkSize; i++) { otherMech = getMechInTempNetwork(i, myNetwork, networkSize); if (!otherMech) continue; if (!Good_obj(otherMech->mynum)) continue; if (mechTarget) { if (otherMech == mechTarget) continue; debugC3(tprintf ("C3RANGE-NETWORK (mech): Finding range from %d to %d.", mech->mynum, mechTarget->mynum)); c3Range = FaMechRange(otherMech, mechTarget); inLOS = InLineOfSight(otherMech, mechTarget, MechX(mechTarget), MechY(mechTarget), c3Range); } else if ((MechTargX(mech) > 0) && (MechTargY(mech) > 0)) { mapX = MechTargX(mech); mapY = MechTargY(mech); map = getMap(mech->mapindex); debugC3(tprintf ("C3RANGE-NETWORK (hex): Finding range from %d to %d %d.", mech->mynum, mapX, mapY)); MechTargZ(mech) = Elevation(map, mapX, mapY); hexZ = ZSCALE * MechTargZ(mech); MapCoordToRealCoord(mapX, mapY, &hexX, &hexY); c3Range = FindRange(MechFX(otherMech), MechFY(otherMech), MechFZ(otherMech), hexX, hexY, hexZ); inLOS = LOS_NB(otherMech, NULL, mapX, mapY, c3Range); } else { continue; } if (inLOS && (c3Range < bestRange)) { bestRange = c3Range; *c3Ref = otherMech->mynum; } } return bestRange; } void debugC3(char *msg) { if (DEBUG_C3) SendDebug(msg); }