void Team::markRadiusSeenToTeams(Stuff::Vector3D& location, float radius, bool shrinkForNight) { if(radius < 0.0) radius = fireVisualRange; if(shrinkForNight) radius -= (radius * 0.25f); bool didTeam[MAX_TEAMS] = {false, false, false, false, false, false, false, false}; for(size_t i = 0; i < ObjectManager->getNumMovers(); i++) { MoverPtr mover = ObjectManager->getMover(i); if(mover->getTeam() && !didTeam[mover->getTeamId()] && !isFriendly(mover->getTeam())) { Stuff::Vector3D result; result.x = location.x - mover->getPosition().x; result.y = location.y - mover->getPosition().y; result.z = 0.0; float dist = result.GetLength() * metersPerWorldUnit; if(dist < maxVisualRange) { markRadiusSeen(location, radius); didTeam[mover->getTeamId()] = true; } } } }
long TeamSensorSystem::getContacts (GameObjectPtr looker, long* contactList, long contactCriteria, long sortType) { if ((sortType != CONTACT_SORT_NONE) && !looker) return(0); static float sortValues[MAX_CONTACTS_PER_SENSOR]; float CV = 0; long numValidContacts = 0; long handleList[MAX_CONTACTS_PER_SENSOR]; for (long i = 0; i < numContacts; i++) { MoverPtr mover = (MoverPtr)ObjectManager->get(contacts[i]); if (!meetsCriteria(looker, mover, contactCriteria)) continue; handleList[numValidContacts] = mover->getHandle(); switch (sortType) { case CONTACT_SORT_NONE: sortValues[numValidContacts] = 0.0; break; case CONTACT_SORT_CV: CV = (float)mover->getCurCV(); sortValues[numValidContacts] = CV; break; case CONTACT_SORT_DISTANCE: sortValues[numValidContacts] = looker->distanceFrom(mover->getPosition()); break; } numValidContacts++; } if ((numValidContacts > 0) && (sortType != CONTACT_SORT_NONE)) { //--------------------------------------------------------- // BIG ASSUMPTION HERE: That a mech will not have more than // MAX_CONTACTS_PER_SENSOR contacts. if (!SensorSystem::sortList) { SensorSystem::sortList = new SortList; if (!SensorSystem::sortList) Fatal(0, " Unable to create Contact sortList "); SensorSystem::sortList->init(MAX_CONTACTS_PER_SENSOR); } bool descendSort = true; if (sortType == CONTACT_SORT_DISTANCE) descendSort = false; SensorSystem::sortList->clear(descendSort); for (long contact = 0; contact < numValidContacts; contact++) { SensorSystem::sortList->setId(contact, handleList[contact]); SensorSystem::sortList->setValue(contact, sortValues[contact]); } SensorSystem::sortList->sort(descendSort); for (contact = 0; contact < numValidContacts; contact++) contactList[contact] = SensorSystem::sortList->getId(contact); } else if (contactList) for (long contact = 0; contact < numValidContacts; contact++) contactList[contact] = handleList[contact]; return(numValidContacts); }
//--------------------------------------------------------------------------- int32_t GameCamera::activate(void) { //------------------------------------------ // If camera is already active, just return if (ready && active) return (NO_ERROR); //--------------------------------------------------------- // Camera always starts pointing at first mover in lists // CANNOT be infinite because we don't allow missions without at least 1 // player mech!! MoverPtr firstMover = nullptr; if (ObjectManager->getNumMovers() > 0) { int32_t i = 0; firstMover = ObjectManager->getMover(i); while (firstMover && ((firstMover->getCommander()->getId() != Commander::home->getId()) || !firstMover->isOnGUI())) { i++; if (i == ObjectManager->getNumMovers()) break; firstMover = ObjectManager->getMover(i); } } if (firstMover) { Stuff::Vector3D newPosition(firstMover->getPosition()); setPosition(newPosition); } if (land) { land->update(); } allNormal(); // updateDaylight(true); lastShadowLightPitch = lightPitch; // Startup the SKYBox int32_t appearanceType = (GENERIC_APPR_TYPE << 24); AppearanceTypePtr genericAppearanceType = nullptr; genericAppearanceType = appearanceTypeList->getAppearance(appearanceType, "skybox"); if (!genericAppearanceType) { char msg[1024]; sprintf(msg, "No Generic Appearance Named %s", "skybox"); Fatal(0, msg); } theSky = new GenericAppearance; gosASSERT(theSky != nullptr); //-------------------------------------------------------------- gosASSERT(genericAppearanceType->getAppearanceClass() == GENERIC_APPR_TYPE); theSky->init((GenericAppearanceType*)genericAppearanceType, nullptr); theSky->setSkyNumber(mission->theSkyNumber); return NO_ERROR; }
Stuff::Vector3D Team::calcEscapeVector(MoverPtr mover, float threatRange) { static float distance[100]; static Stuff::Vector3D delta[100]; Stuff::Vector3D escapeVector; escapeVector.Zero(); //------------------------------ // Get the initial delta info... int32_t shortest = 0; int32_t longest = 0; for(size_t i = 0; i < rosterSize; i++) { GameObjectPtr obj = ObjectManager->getByWatchID(roster[i]); if(obj) { float distanceToObj = mover->distanceFrom(obj->getPosition()); if(distanceToObj <= threatRange) { delta[i].Subtract(mover->getPosition(), obj->getPosition()); distance[i] = distanceToObj; if(distance[i] > longest) longest = i; if(distance[i] < shortest) shortest = i; } else distance[i] = -999.0; } else distance[i] = -999.0; } //----------------------------------------------------------------- // Now, find the furthest enemy and scale the deltas accordingly... for(i = 0; i < rosterSize; i++) if(distance[i] >= 0.0) { float scale = distance[longest] / distance[i]; delta[i] *= scale; escapeVector += delta[i]; } //-------------------------------------------------------------------------------- // We don't care about the length, just the direction (we assume you want to go as // FAR as necessary)... escapeVector.Normalize(escapeVector); return(escapeVector); }
long SensorSystem::calcContactStatus (MoverPtr mover) { if (!owner->getTeam()) return(CONTACT_NONE); if (mover->getFlag(OBJECT_FLAG_REMOVED)) { return(CONTACT_NONE); } //---------------------------------------------------------- //If object we are looking for is at the edge, NO CONTACT!! if (!Terrain::IsGameSelectTerrainPosition(mover->getPosition())) return CONTACT_NONE; //------------------------------------------------------------- // Should be properly set when active probes are implemented... long newContactStatus = CONTACT_NONE; if (!notShutdown || (range == 0.0) && !broken) { if (owner->lineOfSight(mover) && !mover->isDisabled()) newContactStatus = CONTACT_VISUAL; return(newContactStatus); } if ((masterIndex == -1) || (range < 0.0)) { return(CONTACT_NONE); } if (owner->isMover()) { MoverPtr mover = (MoverPtr)owner; if ((mover->sensor == 255) || mover->inventory[mover->sensor].disabled || broken) { return(CONTACT_NONE); } } if (mover->getFlag(OBJECT_FLAG_SENSOR) && !mover->isDisabled()) { bool moverNotContact = mover->hasNullSignature() || (mover->getEcmRange() != 0.0f); bool moverInvisible = (mover->getStatus() == OBJECT_STATUS_SHUTDOWN); if (!moverInvisible && !moverNotContact) { float distanceToMover = owner->distanceFrom(mover->getPosition()); float sensorRange = getEffectiveRange(); if (distanceToMover <= sensorRange) { //------------------------------------------- //No need to check shutdown and probe AGAIN! newContactStatus = getSensorQuality(); //--------------------------------------- // If ecm affecting me, my skill drops... // CUT, per Mitch 2/10/00 if ((ecmEffect < 1.0) && (newContactStatus > CONTACT_SENSOR_QUALITY_1)) newContactStatus--; //--------------------------------------------------- // We now we are within sensor range, check visual. float startRadius = 0.0f; if (!owner->isMover()) startRadius = owner->getAppearRadius(); if (hasLOSCapability && owner->lineOfSight(mover,startRadius)) newContactStatus = CONTACT_VISUAL; } else //Still need to check if visual!!! ECM and Lookout Towers!! { float startRadius = 0.0f; if (!owner->isMover()) startRadius = owner->getAppearRadius(); if (hasLOSCapability && owner->lineOfSight(mover,startRadius)) newContactStatus = CONTACT_VISUAL; } } else { //Target is shutdown, can ONLY be visual cause this platform has no probe. float startRadius = 0.0f; if (!owner->isMover()) startRadius = owner->getAppearRadius(); if (hasLOSCapability && owner->lineOfSight(mover,startRadius)) newContactStatus = CONTACT_VISUAL; } } //Let us know that we can see something, sensor or otherwise!! if (mover->getTeam() && (owner->getTeam() == Team::home) && mover->getTeam()->isEnemy(Team::home) && (newContactStatus != CONTACT_NONE)) { SensorSystemManager::enemyInLOS = true; } return(newContactStatus); }
void GameTacMap::render() { if (turn < 2) //Terrain not setup yet. Left,Right,Top,Bottom are poopy! return; gos_VERTEX corners[5]; gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_OneZero ); gos_SetRenderState( gos_State_Specular,FALSE ); gos_SetRenderState( gos_State_AlphaTest, FALSE ); gos_SetRenderState( gos_State_Filter, gos_FilterNone ); gos_SetRenderState( gos_State_ZWrite, 0 ); gos_SetRenderState( gos_State_ZCompare, 0 ); gos_SetRenderState( gos_State_Texture, textureHandle ); for ( int i = 0; i < 4; ++i ) { corners[i].rhw = 1.0f; corners[i].argb = 0xffffffff; corners[i].frgb = 0; corners[i].z = 0.0f; } corners[0].x = corners[2].x = left; corners[1].x = corners[3].x = right; corners[3].y = corners[2].y = bottom; corners[0].y = corners[1].y = top; corners[0].u = 2.f/(float)bmpWidth; corners[3].u = 128.f/(float)bmpWidth; corners[2].u = 2.f/(float)bmpWidth; corners[1].u = 128.f/(float)bmpWidth; corners[0].v = 2.f/(float)bmpWidth; corners[3].v = 128.f/(float)bmpHeight; corners[2].v = 128.f/(float)bmpHeight; corners[1].v = 2.f/(float)bmpWidth; gos_DrawTriangles( corners, 3 ); gos_DrawTriangles( &corners[1], 3 ); Stuff::Vector2DOf<long> screen; Stuff::Vector4D nScreen; Stuff::Vector3D world; //----------------------------------------------------------- // Render the objective markers long count = 0; for ( EList< CObjective*, CObjective* >::EIterator iter = Team::home->objectives.Begin(); !iter.IsDone(); iter++ ) { //We are there. Start flashing. if ((objectiveAnimationId == count) && objectiveNumFlashes) { objectiveFlashTime += g_deltaTime; if ( objectiveFlashTime > .5f ) { objectiveFlashTime = 0.0f; objectiveNumFlashes--; } else if ( objectiveFlashTime > 0.25f) { (*iter)->RenderMarkers(this, 0); } if (objectiveNumFlashes == 0) { //Flashing is done. We now return you to your regularly scheduled program. objectiveAnimationId = 0; } } else { (*iter)->RenderMarkers(this, 0); } count++; } // this is the little viewing rect // Routine that InverseProjects is slightly less accurate but an order of magnitude faster. // Can make more accurate later at very little expense to performance. // Easy to fix with camera later. -fs screen.x = 1; screen.y = 1; nScreen.x = nScreen.y = 1.0f; nScreen.z = nScreen.w = 0.0f; eye->inverseProjectZ( nScreen, world ); worldToTacMap( world, corners[0] ); screen.y = Environment.screenHeight - 1; nScreen.y = (Environment.screenHeight * 0.6667f) - 1; nScreen.z = nScreen.w = 0.0f; eye->inverseProjectZ( nScreen, world ); worldToTacMap( world, corners[1] ); screen.x = Environment.screenWidth - 1; nScreen.x = Environment.screenWidth - 1; nScreen.z = nScreen.w = 0.0f; eye->inverseProjectZ( nScreen, world ); worldToTacMap( world, corners[2] ); screen.y = 1; nScreen.y = 1; nScreen.z = nScreen.w = 0.0f; eye->inverseProjectZ( nScreen, world ); worldToTacMap( world, corners[3] ); corners[0].argb = 0xffffffff; corners[1].argb = 0xffffffff; corners[2].argb = 0xffffffff; corners[3].argb = 0xffffffff; corners[0].u = corners[1].u = 0.078125f; corners[3].u = corners[2].u = .99875f; corners[0].v = corners[3].v = 0.078125f; corners[1].v = corners[2].v = .99875f; corners[4] = corners[0]; gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha); gos_SetRenderState( gos_State_ShadeMode, gos_ShadeGouraud); gos_SetRenderState( gos_State_MonoEnable, 0); gos_SetRenderState( gos_State_Perspective, 0); gos_SetRenderState( gos_State_Clipping, 2); gos_SetRenderState( gos_State_AlphaTest, 0); gos_SetRenderState( gos_State_Specular, 0); gos_SetRenderState( gos_State_Dither, 1); gos_SetRenderState( gos_State_TextureMapBlend, gos_BlendModulate); gos_SetRenderState( gos_State_Filter, gos_FilterBiLinear); gos_SetRenderState( gos_State_TextureAddress, gos_TextureWrap ); gos_SetRenderState( gos_State_ZCompare, 0); gos_SetRenderState( gos_State_ZWrite, 0); DWORD gosTextureHandle = mcTextureManager->get_gosTextureHandle(viewRectHandle); gos_SetRenderState( gos_State_Texture, gosTextureHandle ); gos_DrawQuads( &corners[0], 4 ); unsigned long colors[MAX_MOVERS]; unsigned long ringColors[MAX_MOVERS]; Stuff::Vector3D positions[MAX_MOVERS]; unsigned long ranges[MAX_MOVERS]; bool selected[MAX_MOVERS]; count = 0; //------------------------------------------------------------ // draw non-movers, must do separate check for vehicles, I'm not sure they // have sensors for ( i = 0; i < MAX_TEAMS; ++i ) { TeamSensorSystem* pSys = SensorManager->getTeamSensor( i ); if ( pSys ) { for ( int j = 0; j < pSys->numSensors; ++j ) { SensorSystem* pSensor = pSys->sensors[j]; if ( !pSensor ) continue; if ( pSensor->owner->isDestroyed() || pSensor->owner->isDisabled() || pSensor->owner->getStatus() == OBJECT_STATUS_SHUTDOWN ) continue; if ( pSensor->getRange() < 1.1 || pSensor->broken) continue; if (!pSensor->owner->getTeam()) continue; ObjectClass objClass = pSensor->owner->getObjectClass(); unsigned long colorBlip = pSensor->owner->getSelected() ? 0xff4bff4b : 0xff00cc00; unsigned long colorRing = 0xff00cc00; if ( pSensor->owner->getTeam()->isNeutral( Team::home ) ) { colorBlip = pSensor->owner->getSelected() ? 0xff4c4cff : 0xff0000ff; colorRing = 0xff0000ff; } else if ( pSensor->owner->getTeam()->isEnemy( Team::home ) ) // enemy { { colorBlip = pSensor->owner->getSelected() ? 0xffff3f3f : 0xffff0000; colorRing = 0xffff0000; } } if ( objClass != BATTLEMECH && objClass != GROUNDVEHICLE) { if ( objClass == ARTILLERY ) { // blink s_lastBlinkTime += g_deltaTime; if ( s_lastBlinkTime > s_blinkLength ) { colorBlip = 0; colorRing = 0; s_lastBlinkTime = 0.f; } } colors[count] = colorBlip; ringColors[count] = colorRing; ranges[count] = pSensor->getRange(); selected[count] = 0; positions[count] = pSensor->owner->getPosition(); count++; } } } } unsigned long colorBlip, colorRing; //----------------------------------------------------- // draw the movers for (i=0;i<(ObjectManager->numMovers);i++) { MoverPtr mover = ObjectManager->getMover(i); if (mover && mover->getExists() && !(mover->isDestroyed() || mover->isDisabled())) { SensorSystem* pSensor = mover->getSensorSystem(); float range = pSensor ? pSensor->getRange() : 0; long contactStatus = mover->getContactStatus(Team::home->getId(), true); if (mover->getTeamId() == Team::home->id) { if (mover->getCommanderId() == Commander::home->getId()) { if (mover->isOnGUI()) { colorBlip = mover->getSelected() ? 0xff4bff4b : 0xff00cc00; mover->getStatus() == OBJECT_STATUS_SHUTDOWN ? colorRing = 0 : colorRing = 0xff00cc00; } else continue; } else { if (mover->isOnGUI() && land->IsGameSelectTerrainPosition(mover->getPosition()) && mover->pathLocks) { colorBlip = mover->getSelected() ? 0xff4b4bff : 0xff0000cc; mover->getStatus() == OBJECT_STATUS_SHUTDOWN ? colorRing = 0 : colorRing = 0xff0000cc; } else continue; } } else if (g_dbgShowMovers || (MPlayer && MPlayer->allUnitsDestroyed[MPlayer->commanderID]) || ((mover->getTeamId() != Team::home->id) && ( contactStatus != CONTACT_NONE ) && (mover->getStatus() != OBJECT_STATUS_SHUTDOWN) && (!mover->hasNullSignature()) && (mover->getEcmRange() <= 0.0f) ) ) //Do not draw ECM mechs!!) { //Not on our side. Draw by contact status colorBlip = mover->getSelected() ? 0xffff3f3f : 0xffff0000; colorRing = 0xffff0000; } else continue; colors[count] = colorBlip; ringColors[count] = colorRing; ranges[count] = range; selected[count] = mover->getSelected(); positions[count] = mover->getPosition(); count++; } } for ( i = 0; i < count; i++ ) { drawSensor( positions[i], ranges[i], ringColors[i] ); } bool bSel = 0; // draw unselected first for ( int j = 0; j < 2; j++ ) { for ( int i = 0; i < count; i++ ) { if ( selected[i] == bSel ) { drawBlip( positions[i], colors[i], DOT_BLIP ); } } bSel = 1; } }
//--------------------------------------------------------------------------- bool Team::teamLineOfSight(Stuff::Vector3D tPos, float extRad) { //----------------------------------------------------------- // For each member of the team, check LOS to point provided. for(size_t i = 0; i < rosterSize; i++) { MoverPtr obj = (MoverPtr)ObjectManager->getByWatchID(roster[i]); if(!obj->isDisabled() && !obj->isDestroyed() && (obj->getStatus() != OBJECT_STATUS_SHUTDOWN)) { Stuff::Vector3D distance; distance.Subtract(tPos, obj->getPosition()); float dist = distance.GetApproximateLength(); //Figure out altitude above minimum terrain altitude and look up in table. float baseElevation = MapData::waterDepth; if(MapData::waterDepth < Terrain::userMin) baseElevation = Terrain::userMin; float altitude = obj->getPosition().z - baseElevation; float altitudeIntegerRange = (Terrain::userMax - baseElevation) * 0.00390625f; int32_t altLevel = 0; if(altitudeIntegerRange > Stuff::SMALL) altLevel = altitude / altitudeIntegerRange; if(altLevel < 0) altLevel = 0; if(altLevel > 255) altLevel = 255; float radius = visualRangeTable[altLevel]; //Scouting specialty skill. if(obj->isMover()) { MoverPtr mover = (MoverPtr)obj; if(mover->pilot && mover->pilot->isScout()) radius += (radius * 0.2f); radius *= mover->getLOSFactor(); } if(dist <= (radius * 25.0f * worldUnitsPerMeter)) { if(lineOfSight(obj->getLOSPosition(), tPos, id, extRad, 0.0f, false)) return true; } } } //------------------------------------------------------------------------- // Check the lookout towers now. You can find them in special Buildings!! for(size_t spBuilding = 0; spBuilding < ObjectManager->numSpecialBuildings; spBuilding++) { if(ObjectManager->specialBuildings[spBuilding] && ObjectManager->specialBuildings[spBuilding]->getExists() && ObjectManager->specialBuildings[spBuilding]->isLookoutTower() && (ObjectManager->specialBuildings[spBuilding]->getTeamId() == id)) { GameObjectPtr obj = ObjectManager->specialBuildings[spBuilding]; if(!obj->isDisabled() && !obj->isDestroyed() && (obj->getStatus() != OBJECT_STATUS_SHUTDOWN)) { Stuff::Vector3D distance; distance.Subtract(tPos, obj->getPosition()); float dist = distance.GetApproximateLength(); //Figure out altitude above minimum terrain altitude and look up in table. float baseElevation = MapData::waterDepth; if(MapData::waterDepth < Terrain::userMin) baseElevation = Terrain::userMin; float altitude = obj->getPosition().z - baseElevation; float altitudeIntegerRange = (Terrain::userMax - baseElevation) * 0.00390625f; int32_t altLevel = 0; if(altitudeIntegerRange > Stuff::SMALL) altLevel = altitude / altitudeIntegerRange; if(altLevel < 0) altLevel = 0; if(altLevel > 255) altLevel = 255; float radius = visualRangeTable[altLevel]; //Scouting specialty skill. if(obj->isMover()) { MoverPtr mover = (MoverPtr)obj; if(mover->pilot && mover->pilot->isScout()) radius += (radius * 0.2f); radius *= mover->getLOSFactor(); } if(dist <= (radius * 25.0f * worldUnitsPerMeter)) { if(lineOfSight(obj->getLOSPosition(), tPos, id, 0.0f, obj->getAppearRadius(), false)) return true; } } } } return false; }