12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835 |
- //***************************************************************************
- //
- // artlry.cpp -- File contains the Artillery Strike Object code
- //
- // MechCommander 2
- //
- //---------------------------------------------------------------------------//
- // Copyright (C) Microsoft Corporation. All rights reserved. //
- //===========================================================================//
- #ifndef MCLIB_H
- #include "mclib.h"
- #endif
- #ifndef ARTLRY_H
- #include "artlry.h"
- #endif
- #ifndef TEAM_H
- #include "team.h"
- #endif
- #ifndef OBJMGR_H
- #include "objmgr.h"
- #endif
- #ifndef MOVE_H
- #include "move.h"
- #endif
- #ifndef CARNAGE_H
- #include "carnage.h"
- #endif
- #ifndef COLLSN_H
- #include "collsn.h"
- #endif
- #ifndef TURRET_H
- #include "turret.h"
- #endif
- #ifndef TERRAIN_H
- #include "terrain.h"
- #endif
- #ifndef COMNDR_H
- #include "comndr.h"
- #endif
- #ifndef MISSION_H
- #include "mission.h"
- #endif
- #ifndef GATE_H
- #include "gate.h"
- #endif
- #ifndef GAMESOUND_H
- #include "gamesound.h"
- #endif
- #ifndef MULTPLYR_H
- #include "multplyr.h"
- #endif
- //---------------------------------------------------------------------------
- //extern float worldUnitsPerMeter;
- //extern ObjectMapPtr GameObjectMap;
- //long NumCameraDrones = 0;
- #define ARTILLERYCHUNK_COMMANDERID_BITS 3
- #define ARTILLERYCHUNK_STRIKETYPE_BITS 3
- #define ARTILLERYCHUNK_CELLPOS_BITS 10
- #define ARTILLERYCHUNK_SECONDS_BITS 6
- #define ARTILLERYCHUNK_COMMANDERID_MASK 0x00000007
- #define ARTILLERYCHUNK_STRIKETYPE_MASK 0x00000007
- #define ARTILLERYCHUNK_CELLPOS_MASK 0x000003FF
- #define ARTILLERYCHUNK_SECONDS_MASK 0x0000003F
- extern MidLevelRenderer::MLRClipper * theClipper;
- extern bool useShadows;
- #define AIRSTRIKE_NAME "airstrikemarker"
- #define SENSOR_NAME "sensormarker"
- #define GV_LEFT_DUST_ID 0
- #define GV_RIGHT_DUST_ID 1
- extern bool MLRVertexLimitReached;
- //***************************************************************************
- // MISC
- //***************************************************************************
- void CallArtillery (long commanderID, long strikeType, Stuff::Vector3D strikeLoc, long secondsToImpact, bool randomOff)
- {
- //-------------------------------------------------------------------
- // If this commander already has 10 strikes going and I'm the server,
- // then no more! If I'm a client, trust the server...
- long numArtillery = 0;
- for (long i = 0; i < ObjectManager->getNumArtillery(); i++)
- {
- ArtilleryPtr artillery = ObjectManager->getArtillery(i);
- if (artillery && artillery->getExists() && (artillery->getCommanderId() == commanderID))
- numArtillery++;
- }
- if (numArtillery >= 10)
- {
- if (MPlayer && MPlayer->isServer())
- return;
- }
- ArtilleryPtr artilleryStrike = ObjectManager->createArtillery(strikeType,strikeLoc);
- if (artilleryStrike)
- {
- artilleryStrike->iFacePosition = strikeLoc;
- artilleryStrike->setPosition( strikeLoc );
-
- //-----------------------------------------------------------
- // alignment only really matters for sensor & camera strikes.
- artilleryStrike->setTeamId(Commander::commanders[commanderID]->getTeam()->getId(), true);
- artilleryStrike->setCommanderId(commanderID);
-
- //-----------------------------------------------------------
- // Set Time to Impact here. Only if timeToImpact is != -1.0
- if (secondsToImpact != -1)
- artilleryStrike->info.strike.timeToImpact = (float)secondsToImpact;
-
- // Of course, then our friends the designers set
- // secondsToImpact to 0. Well Done. No warning. Looks like
- // a bug don't it?
- // MINIMUM time to impact is now four!!!!!
- if (secondsToImpact < 2)
- artilleryStrike->info.strike.timeToImpact = -1; //FULL Duration.
-
- //------------------------------------
- // We must be server if we got here...
- if (MPlayer) {
- if ((strikeType == ARTILLERY_SMALL) || (strikeType == ARTILLERY_LARGE))
- MPlayer->numAirStrikesUsed[commanderID]++;
- else
- MPlayer->numSensorProbesUsed[commanderID]++;
- if (MPlayer->isServer())
- MPlayer->addArtilleryChunk(commanderID, strikeType, strikeLoc, secondsToImpact);
- }
-
- artilleryStrike->update(); // call this so if in pause mode, there is something to draw
- }
- }
- //---------------------------------------------------------------------------
- void IfaceCallStrike (long strikeID,
- Stuff::Vector3D* strikeLoc,
- GameObjectPtr strikeTarget,
- bool playerStrike,
- bool clanStrike,
- float timeToImpact)
- {
- if ((strikeID != ARTILLERY_LARGE) && (strikeID != ARTILLERY_SMALL) && (strikeID != ARTILLERY_SENSOR))
- return;
- if (!strikeLoc && !strikeTarget)
- return;
- Stuff::Vector3D strikeLocation;
- if (strikeLoc)
- strikeLocation = *strikeLoc;
- else
- strikeLocation = strikeTarget->getPosition();
- bool bRandom = 0;
- long commanderID = -1;
- if (playerStrike)
- {
- commanderID = Commander::home->getId();
- bRandom = Team::home->teamLineOfSight(*strikeLoc,0.0f) ? 0 : 1;
- }
- else if (clanStrike)
- {
- if (MPlayer)
- Fatal(0, " Iface.CallStrike: Need more info than clanStrike in MPlayer ");
- //------------------------------------------------------------
- // In campaign game, clans can strike into unrevealed terrain.
- bRandom = Team::teams[1]->teamLineOfSight(*strikeLoc,0.0f) ? 0 : 1;
- commanderID = 1;
- }
- switch (strikeID)
- {
- case ARTILLERY_LARGE:
- case ARTILLERY_SMALL:
- if (playerStrike && Team::home->teamLineOfSight(strikeLocation,0.0f))
- {
- soundSystem->playDigitalSample(MAPBUTTONS_GUI);
- }
- break;
- }
- long secondsToImpact = (long)timeToImpact;
- if (strikeID == ARTILLERY_SMALL)
- strikeID = ARTILLERY_LARGE;
- if (strikeID == ARTILLERY_LARGE && bRandom)
- strikeID = ARTILLERY_SMALL;
- if (MPlayer)
- {
- if (MPlayer->isServer())
- {
- CallArtillery(commanderID, strikeID, strikeLocation, secondsToImpact, bRandom);
- }
- else
- {
- MPlayer->sendPlayerArtillery(strikeID, strikeLocation, secondsToImpact);
- }
- }
- else
- {
- CallArtillery(commanderID, strikeID, strikeLocation, secondsToImpact, bRandom);
- }
- }
- //***************************************************************************
- // ARTILLERY CHUNK
- //***************************************************************************
- void* ArtilleryChunk::operator new (size_t ourSize) {
- void* result;
- result = systemHeap->Malloc(ourSize);
- return(result);
- }
- //---------------------------------------------------------------------------
- void ArtilleryChunk::operator delete (void* us) {
- systemHeap->Free(us);
- }
- //---------------------------------------------------------------------------
- void ArtilleryChunk::build (long _commanderId,
- long _strikeType,
- Stuff::Vector3D location,
- long _seconds) {
- commanderId = _commanderId;
- strikeType = _strikeType;
- land->worldToCell(location, cellRC[0], cellRC[1]);
- secondsToImpact = _seconds;
- data = 0;
- }
- //---------------------------------------------------------------------------
- void ArtilleryChunk::pack (void) {
- data = 0;
- data |= (secondsToImpact + 1);
- data <<= ARTILLERYCHUNK_CELLPOS_BITS;
- data |= cellRC[0];
- data <<= ARTILLERYCHUNK_CELLPOS_BITS;
- data |= cellRC[1];
- data <<= ARTILLERYCHUNK_STRIKETYPE_BITS;
- data |= strikeType;
- data <<= ARTILLERYCHUNK_COMMANDERID_BITS;
- data |= commanderId;
- }
- //---------------------------------------------------------------------------
-
- void ArtilleryChunk::unpack (void) {
- unsigned long tempData = data;
- commanderId = (tempData & ARTILLERYCHUNK_COMMANDERID_MASK);
- tempData >>= ARTILLERYCHUNK_COMMANDERID_BITS;
- strikeType = (tempData & ARTILLERYCHUNK_STRIKETYPE_MASK);
- tempData >>= ARTILLERYCHUNK_STRIKETYPE_BITS;
- cellRC[1] = (tempData & ARTILLERYCHUNK_CELLPOS_MASK);
- tempData >>= ARTILLERYCHUNK_CELLPOS_BITS;
- cellRC[0] = (tempData & ARTILLERYCHUNK_CELLPOS_MASK);
- tempData >>= ARTILLERYCHUNK_CELLPOS_BITS;
- secondsToImpact = (tempData & ARTILLERYCHUNK_SECONDS_MASK) - 1;
- }
- //---------------------------------------------------------------------------
- bool ArtilleryChunk::equalTo (ArtilleryChunkPtr chunk) {
- if (commanderId != chunk->commanderId)
- return(false);
- if (strikeType != chunk->strikeType)
- return(false);
- if (cellRC[0] != chunk->cellRC[0])
- return(false);
- if (cellRC[1] != chunk->cellRC[1])
- return(false);
- if (secondsToImpact != chunk->secondsToImpact)
- return(false);
- return(true);
- }
- //***************************************************************************
- // class ArtilleryType
- //***************************************************************************
- GameObjectPtr ArtilleryType::createInstance (void) {
- ArtilleryPtr newArtillery = new Artillery;
- if (!newArtillery)
- return(NULL);
- newArtillery->init(true, this);
- return(newArtillery);
- }
- //---------------------------------------------------------------------------
- void ArtilleryType::init (void) {
- ObjectType::init();
- objectTypeClass = ARTILLERY_TYPE;
- objectClass = ARTILLERY;
- }
- //---------------------------------------------------------------------------
- void ArtilleryType::destroy (void)
- {
- if (explosionOffsetX)
- {
- systemHeap->Free(explosionOffsetX);
- explosionOffsetX = NULL;
- }
- if (explosionOffsetY)
- {
- systemHeap->Free(explosionOffsetY);
- explosionOffsetY = NULL;
- }
- if (explosionDelay)
- {
- systemHeap->Free(explosionDelay);
- explosionDelay = NULL;
- }
- ObjectType::destroy();
- }
-
- //---------------------------------------------------------------------------
- long ArtilleryType::init (FilePtr objFile, unsigned long fileSize) {
- long result = 0;
-
- FitIniFile miFile;
- result = miFile.open(objFile,fileSize);
- if (result != NO_ERR)
- return(result);
- //---------------------------------------------------------------
- // Load up the artillery data.
- result = miFile.seekBlock("Artillery");
- if (result != NO_ERR)
- return(result);
-
- char artillerySpriteName[80];
- result = miFile.readIdString("ArtillerySpriteName",artillerySpriteName,79);
- if (result != NO_ERR)
- return(result);
-
- result = miFile.readIdULong("FrameCount",frameCount);
- if (result != NO_ERR)
- return(result);
-
- result = miFile.readIdULong("StartFrame",startFrame);
- if (result != NO_ERR)
- return(result);
-
- result = miFile.readIdFloat("FrameRate",frameRate);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("NominalTimeToImpact",nominalTimeToImpact);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("NominalTimeToLaunch",nominalTimeToLaunch);
- if (result != NO_ERR)
- nominalTimeToLaunch = nominalTimeToImpact - 10;
- result = miFile.readIdFloat("NominalDamage",nominalDamage);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("NominalMajorRange",nominalMajorRange);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("NominalMajorHits",nominalMajorHits);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("NominalMinorRange",nominalMinorRange);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("NominalMinorHits",nominalMinorHits);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("NominalSensorTime",nominalSensorTime);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("NominalSensorRange",nominalSensorRange);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("fontScale",fontScale);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("fontXOffset",fontXOffset);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdFloat("fontYOffset",fontYOffset);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdULong("fontColor",fontColor);
- if (result != NO_ERR)
- return(result);
-
- if (nominalDamage)
- {
- result = miFile.readIdLong("NumExplosions",numExplosions);
- if (result != NO_ERR)
- return(result);
-
- explosionOffsetX = (float *)systemHeap->Malloc(sizeof(float)*numExplosions);
- gosASSERT(explosionOffsetX != NULL);
- explosionOffsetY = (float *)systemHeap->Malloc(sizeof(float)*numExplosions);
- gosASSERT(explosionOffsetY != NULL);
- explosionDelay = (float *)systemHeap->Malloc(sizeof(float)*numExplosions);
- gosASSERT(explosionDelay != NULL);
- for (long i=0;i<numExplosions;i++)
- {
- char explosionId[50];
- sprintf(explosionId,"ExplosionDelay%d",i);
- result = miFile.readIdFloat(explosionId,explosionDelay[i]);
- if (result != NO_ERR)
- return(result);
-
- sprintf(explosionId,"ExplosionOffsetX%d",i);
- result = miFile.readIdFloat(explosionId,explosionOffsetX[i]);
- if (result != NO_ERR)
- return(result);
- sprintf(explosionId,"ExplosionOffsetY%d",i);
- result = miFile.readIdFloat(explosionId,explosionOffsetY[i]);
- if (result != NO_ERR)
- return(result);
- }
- result = miFile.readIdLong("ExplosionsPerExplosion",numExplosionsPerExplosion);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdLong("ExplosionRandomOffsetX",explosionRandomX);
- if (result != NO_ERR)
- return(result);
-
- result = miFile.readIdLong("ExplosionRandomOffsetY",explosionRandomY);
- if (result != NO_ERR)
- return(result);
- result = miFile.readIdLong("MinArtilleryHeadRange",minArtilleryHeadRange);
- if (result != NO_ERR)
- minArtilleryHeadRange = 5.0;
- }
- else
- {
- explosionOffsetX = explosionOffsetY = explosionDelay = NULL;
- }
- //-------------------------------------------------------
- // Initialize the base object Type from the current file.
- result = ObjectType::init(&miFile);
- return(result);
- }
-
- //---------------------------------------------------------------------------
- bool ArtilleryType::handleCollision (GameObjectPtr collidee, GameObjectPtr collider)
- {
- if (MPlayer && !MPlayer->isServer())
- return(false);
- //----------------------------------------------------------
- // Artillery counts as damage IF AND ONLY IF the artillery
- // strike arrives during the collision time. At all other
- // times, the artillery doesn't matter.
- ArtilleryPtr artillery = (ArtilleryPtr)collidee;
- ArtilleryTypePtr artilleryType = (ArtilleryTypePtr)artillery->getObjectType();
- if (artillery->getFlag(OBJECT_FLAG_BOOM))
- {
- //---------------------
- // Get Range to target.
- Stuff::Vector3D distance = collider->getPosition();
- distance -= collidee->getPosition();
- distance.z = 0.0; //Do NOT use elevation!!! Will make it look like its not WORKING!!!!
- float range = distance.GetLength() * metersPerWorldUnit;
- if ((collider->getObjectClass() == GATE) || (collider->getObjectClass() == TURRET))
- {
- switch (collider->getObjectClass())
- {
- case GATE:
- {
- //---------------------------------------------------
- // An explosion may NOT damage a gate or turret unless
- // is is within the "little" extent radius.
- float littleExtent = ((GatePtr)collider)->getLittleExtent() * metersPerWorldUnit;
- if (littleExtent < range)
- {
- float realRange = range - littleExtent;
- if (realRange > ((ArtilleryTypePtr)artillery->getObjectType())->nominalMajorRange)
- return FALSE;
- }
- }
- break;
-
- case TURRET:
- {
- //---------------------------------------------------
- // An explosion may NOT damage a gate or turret unless
- // is is within the "little" extent radius.
- float littleExtent = ((TurretPtr)collider)->getLittleExtent() * metersPerWorldUnit;
- if (littleExtent < range)
- {
- float realRange = range - littleExtent;
- if (realRange > artilleryType->nominalMajorRange)
- return(false);
- }
- }
- break;
- }
- }
- else if ((collider->getObjectClass() == BATTLEMECH) &&
- (((MoverPtr)collider)->getMoveType() == MOVETYPE_AIR) &&
- (collider->getStatus() != OBJECT_STATUS_SHUTDOWN))
- {
- //DO Nothing. Helicopters are immune.
- return false;
- }
-
- bool isMajorHit = (range <= artilleryType->nominalMajorRange);
- long numHits = artilleryType->nominalMajorHits;
- if (!isMajorHit)
- numHits = artilleryType->nominalMinorHits;
-
- for (long i = 0; i < numHits; i++)
- {
- WeaponShotInfo shot;
- shot.init(collidee->getWatchID(), -3, artilleryType->nominalDamage, 0, 0);
- if (collider->isMover())
- {
- if (range <= minArtilleryHeadRange)
- shot.hitLocation = collider->calcHitLocation(collidee, -1, ATTACKSOURCE_DFA, 0);
- else
- shot.hitLocation = collider->calcHitLocation(collidee, -1, ATTACKSOURCE_ARTILLERY, 0);
- shot.setEntryAngle(collider->relFacingTo(collidee->getPosition()));
- }
- collider->handleWeaponHit(&shot, (MPlayer != NULL));
- }
- }
-
- return(false);
- }
- //---------------------------------------------------------------------------
- bool ArtilleryType::handleDestruction (GameObjectPtr collidee, GameObjectPtr collider)
- {
- //-------------------------------------------------------
- // Artillery goes away when it hits. Nothing happens as
- // a result of a collision.
- return(false);
- }
- //***************************************************************************
- // class Artillery
- //***************************************************************************
- void Artillery::init (bool create)
- {
- artilleryType = ARTILLERY_SMALL;
- initFlags();
- setFlag(OBJECT_FLAG_JUSTCREATED, true);
-
- info.strike.timeToImpact = -1.0;
- info.strike.timeToLaunch = -1.0;
-
- info.strike.sensorRange = 0.0;
- info.strike.contactUpdate = scenarioTime;
- info.strike.sensorSystemIndex = -1;
- info.strike.timeToBlind = 0.0;
-
- hitEffect = NULL;
- leftContrail = NULL;
- rightContrail = NULL;
-
- bomber = NULL;
-
- setFlag(OBJECT_FLAG_RANDOM_OFFSET, 0);
- }
- //---------------------------------------------------------------------------
- void Artillery::init (bool create, long _artilleryType)
- {
- init(create);
- artilleryType = _artilleryType;
- if (isStrike())
- {
- }
- else if (isSensor())
- {
- }
- }
- //---------------------------------------------------------------------------
- void Artillery::handleStaticCollision (void)
- {
- if (getFlag(OBJECT_FLAG_TANGIBLE))
- {
- //-----------------------------------------------------
- // What is our block and vertex number?
- long blockNumber = 0;
- long vertexNumber = 0;
-
- getBlockAndVertexNumber(blockNumber,vertexNumber);
- long CellRow, CellCol;
- land->worldToCell(getPosition(), CellRow, CellCol);
-
- //-------------------------------------------------------
- // MUST figure out radius to set off mines in CELLS now.
- // -fs
- long startCellRow = CellRow - 4;
- long startCellCol = CellCol - 4;
-
- long i=0;
- for (i = startCellRow; i < startCellRow + 9; i++)
- {
- for (long j = startCellCol; j < startCellCol + 9; j++)
- {
- if (GameMap->inBounds(i,j))
- {
- long mineResult = 0;
- mineResult = GameMap->getMine(i,j);
-
- if (mineResult == 1)
- {
- Stuff::Vector3D minePosition;
- land->cellToWorld(i,j,minePosition);
- GameMap->setMine(i,j,2);
- if (MPlayer)
- {
- MPlayer->addMineChunk(i,
- j,
- 1,
- 2,
- 2);
- }
- ObjectManager->createExplosion(MINE_EXPLOSION_ID, NULL, minePosition, MineSplashDamage, MineSplashRange * worldUnitsPerMeter);
- }
- }
- }
- }
-
- //-------------------------------------------------------------------------
- // We must now move out into other tiles for the artillery strike to work.
- // Remember, Its pretty big!
- // Just grab the nine vertices around this one. Problems arise when on Block border. Handle it.
- blockNumber = 0;
- vertexNumber = 0;
- getBlockAndVertexNumber(blockNumber,vertexNumber);
-
- //-------------------------------------------------------------------------
- // We must now move out into other tiles for the artillery strike to work.
- // Remember, Its pretty big!
- // Just grab the nine vertices around this one. Problems arise when on Block border. Handle it.
- long topLeftBlockNumber = blockNumber - Terrain::blocksMapSide - 1;
- long currentBlockNumber = topLeftBlockNumber;
- long totalBlocks = Terrain::blocksMapSide * Terrain::blocksMapSide;
- for (i = 0; i < 3; i++)
- {
- for (long j = 0; j < 3; j++)
- {
- if ((currentBlockNumber >= 0) && (currentBlockNumber < totalBlocks))
- {
- long numObjectsInBlock = ObjectManager->getObjBlockNumObjects(currentBlockNumber);
- for (long objIndex = 0; objIndex < numObjectsInBlock; objIndex++)
- {
- GameObjectPtr obj = ObjectManager->getObjBlockObject(currentBlockNumber, objIndex);
- if (!obj)
- STOP(("Object Number %d in terrain Block %d was NULL!",objIndex,currentBlockNumber));
- if (obj->getExists())
- ObjectManager->detectStaticCollision(this, obj);
- }
- }
- currentBlockNumber++;
- }
- currentBlockNumber = topLeftBlockNumber + (Terrain::blocksMapSide * (i + 1));
- }
- }
- }
- //---------------------------------------------------------------------------
- void Artillery::setJustCreated (void)
- {
- if (getFlag(OBJECT_FLAG_JUSTCREATED))
- {
- ArtilleryTypePtr type = (ArtilleryTypePtr)getObjectType();
- setFlag(OBJECT_FLAG_JUSTCREATED, false);
- if (info.strike.timeToImpact == -1.0)
- info.strike.timeToImpact = type->nominalTimeToImpact;
-
- info.strike.timeToLaunch = type->nominalTimeToLaunch;
- info.strike.sensorRange = type->nominalSensorRange;
- info.strike.timeToBlind = 0.0;
- setFlag(OBJECT_FLAG_TANGIBLE, false);
- setFlag(OBJECT_FLAG_SENSORS_GOING, false);
- if (info.strike.sensorRange)
- {
- long cellR, cellC;
- land->worldToCell(position,cellR, cellC);
- if (GameMap->getDeepWater(cellR, cellC) || GameMap->getShallowWater(cellR, cellC))
- effectId--;
- }
-
- //Create the GOSFX here.
- if (strcmp(weaponEffects->GetEffectName(effectId),"NONE") != 0)
- {
- //--------------------------------------------
- // Yes, load it on up.
- unsigned flags = gosFX::Effect::ExecuteFlag;
-
- Check_Object(gosFX::EffectLibrary::Instance);
- gosFX::Effect::Specification* gosEffectSpec = gosFX::EffectLibrary::Instance->Find(weaponEffects->GetEffectName(effectId));
-
- if (gosEffectSpec)
- {
- hitEffect = gosFX::EffectLibrary::Instance->MakeEffect(gosEffectSpec->m_effectID, flags);
- gosASSERT(hitEffect != NULL);
-
- MidLevelRenderer::MLRTexturePool::Instance->LoadImages();
- }
- }
-
- if (strcmp(weaponEffects->GetEffectName(JET_CONTRAIL_ID),"NONE") != 0)
- {
- //--------------------------------------------
- // Yes, load it on up.
- unsigned flags = gosFX::Effect::ExecuteFlag;
-
- Check_Object(gosFX::EffectLibrary::Instance);
- gosFX::Effect::Specification* gosEffectSpec = gosFX::EffectLibrary::Instance->Find(weaponEffects->GetEffectName(JET_CONTRAIL_ID));
-
- if (gosEffectSpec)
- {
- //leftContrail = gosFX::EffectLibrary::Instance->MakeEffect(gosEffectSpec->m_effectID, flags);
- //gosASSERT(leftContrail != NULL);
-
- rightContrail = gosFX::EffectLibrary::Instance->MakeEffect(gosEffectSpec->m_effectID, flags);
- gosASSERT(rightContrail != NULL);
-
- MidLevelRenderer::MLRTexturePool::Instance->LoadImages();
- }
- }
-
- if (info.strike.sensorRange)
- {
- SensorSystemPtr sensor = SensorManager->newSensor();
- info.strike.sensorSystemIndex = sensor->id;
- setSensorData(getTeam());
-
- if ((info.strike.timeToBlind == 0.0f) && !getFlag(OBJECT_FLAG_SENSORS_GOING))
- {
- if (hitEffect)
- {
- Stuff::LinearMatrix4D shapeOrigin;
-
- Stuff::Point3D actualPosition;
- actualPosition.x = -position.x;
- actualPosition.y = position.z;
- actualPosition.z = position.y;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- gosFX::Effect::ExecuteInfo info((Stuff::Time)scenarioTime,&shapeOrigin,NULL);
- hitEffect->Start(&info);
- }
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- long Artillery::update (void)
- {
- if (getFlag(OBJECT_FLAG_JUSTCREATED))
- {
- setJustCreated();
- }
- else
- {
- info.strike.timeToImpact -= frameLength;
- info.strike.timeToLaunch -= frameLength;
- }
- ArtilleryTypePtr type = (ArtilleryTypePtr)getObjectType();
-
- recalcBounds(eye); //Are we even visible?
- if (inView)
- {
- windowsVisible = turn;
- }
-
- //-------------------------------------------------------------------------------
- // Special Cases here. If we are an explosive round, let everyone know we went.
- if (getFlag(OBJECT_FLAG_BOOM) && (type->nominalDamage > 0.0))
- {
- setFlag(OBJECT_FLAG_TANGIBLE, false);
-
- //------------------------------------------------
- // Update GOSFX
- if (hitEffect && hitEffect->IsExecuted())
- {
- Stuff::Point3D actualPosition;
- actualPosition.x = -position.x;
- actualPosition.y = position.z;
- actualPosition.z = position.y;
-
- Stuff::LinearMatrix4D shapeOrigin;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- Stuff::OBB boundingBox;
- gosFX::Effect::ExecuteInfo info((Stuff::Time)scenarioTime,&shapeOrigin,&boundingBox);
-
- bool result = hitEffect->Execute(&info);
- if (!result)
- {
- hitEffect->Kill(); //Effect is over. Otherwise, wait until hit!
- delete hitEffect;
- hitEffect = NULL;
-
- if (bomber)
- {
- delete bomber;
- bomber = NULL;
- }
-
- if (leftContrail)
- {
- leftContrail->Kill();
- delete leftContrail;
- leftContrail = NULL;
- }
-
- if (rightContrail)
- {
- rightContrail->Kill();
- delete rightContrail;
- rightContrail = NULL;
- }
-
- return false; //Strike is also over
- }
- }
- }
-
- if ((info.strike.timeToImpact > 0.0f) || (type->nominalDamage == 0.0))
- {
- bool oldShadows = useShadows;
- useShadows = false;
- appearance->setObjectParameters(iFacePosition,((ObjectAppearance*)appearance)->rotation,false,getTeamId(),Team::getRelation(getTeamId(), Team::home->getId()));
- appearance->recalcBounds();
- appearance->update();
- useShadows = oldShadows;
- }
-
- if (bomber && (info.strike.timeToImpact <= 2.5f) && !bombRunStarted)
- {
- bomber->setObjectParameters(position,0.0f,false,getTeamId(),Team::getRelation(getTeamId(), Team::home->getId()));
- bomber->setMoverParameters(0.0f);
- bomber->setGesture(0);
- bomber->setObjStatus(OBJECT_STATUS_DESTROYED);
- bomber->recalcBounds();
- bomber->setVisibility(true,true);
- bomber->update(); //Force it to try and draw or stuff will not work!
- bombRunStarted = true;
-
- if (rightContrail && rightContrail->IsExecuted())
- {
- Stuff::LinearMatrix4D shapeOrigin;
-
- Stuff::Vector3D lPosition = bomber->getNodeNamePosition("activity_node");
-
- Stuff::Point3D actualPosition;
- actualPosition.x = -lPosition.x;
- actualPosition.y = lPosition.z;
- actualPosition.z = lPosition.y;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- gosFX::Effect::ExecuteInfo info((Stuff::Time)scenarioTime,&shapeOrigin,NULL);
- rightContrail->Start(&info);
- }
-
- if (leftContrail && leftContrail->IsExecuted())
- {
- Stuff::LinearMatrix4D shapeOrigin;
-
- Stuff::Vector3D lPosition = bomber->getDustNodePosition(GV_LEFT_DUST_ID);
-
- Stuff::Point3D actualPosition;
- actualPosition.x = -lPosition.x;
- actualPosition.y = lPosition.z;
- actualPosition.z = lPosition.y;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- gosFX::Effect::ExecuteInfo info((Stuff::Time)scenarioTime,&shapeOrigin,NULL);
- leftContrail->Start(&info);
- }
- }
-
- if (bomber && bombRunStarted)
- {
- bomber->setObjectParameters(position,0.0f,false,getTeamId(),Team::getRelation(getTeamId(), Team::home->getId()));
- bomber->recalcBounds();
- bomber->setVisibility(true,true);
- bomber->update();
-
- if (bomber && leftContrail && leftContrail->IsExecuted())
- {
- Stuff::Vector3D lPosition = bomber->getDustNodePosition(GV_LEFT_DUST_ID);
-
- Stuff::Point3D actualPosition;
- actualPosition.x = -lPosition.x;
- actualPosition.y = lPosition.z;
- actualPosition.z = lPosition.y;
-
- Stuff::LinearMatrix4D shapeOrigin;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- Stuff::OBB boundingBox;
- gosFX::Effect::ExecuteInfo info((Stuff::Time)scenarioTime,&shapeOrigin,&boundingBox);
-
- leftContrail->Execute(&info);
- }
-
- if (bomber && rightContrail && rightContrail->IsExecuted())
- {
- Stuff::Vector3D lPosition = bomber->getNodeNamePosition("activity_node");
-
- Stuff::Point3D actualPosition;
- actualPosition.x = -lPosition.x;
- actualPosition.y = lPosition.z;
- actualPosition.z = lPosition.y;
-
- Stuff::LinearMatrix4D shapeOrigin;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- Stuff::OBB boundingBox;
- gosFX::Effect::ExecuteInfo info((Stuff::Time)scenarioTime,&shapeOrigin,&boundingBox);
-
- rightContrail->Execute(&info);
- }
- }
-
- if ((info.strike.timeToImpact <= 5.5) && !getFlag(OBJECT_FLAG_WHOOSH))
- {
- if (soundSystem && (type->nominalDamage > 0.0))
- {
- setFlag(OBJECT_FLAG_WHOOSH, true);
- soundSystem->playDigitalSample(INCOMING_AIRSTRIKE,position,true);
- }
- }
- if (!getFlag(OBJECT_FLAG_BOOM) && (info.strike.timeToImpact <= 0.0) && (type->nominalDamage > 0.0))
- {
- Stuff::Vector3D actualPosition = position;
- //-----------------------------------
- // Create the giant artillery blast.
- // GOS Fx now.
- if (hitEffect && hitEffect->IsExecuted())
- {
- Stuff::LinearMatrix4D shapeOrigin;
-
- Stuff::Point3D actualPosition;
- actualPosition.x = -position.x;
- actualPosition.y = position.z;
- actualPosition.z = position.y;
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- gosFX::Effect::ExecuteInfo info((Stuff::Time)scenarioTime,&shapeOrigin,NULL);
- hitEffect->Start(&info);
- }
-
- //------------------------------------------------
- // Update GOSFX -- One free update here.
- if (hitEffect && hitEffect->IsExecuted())
- {
- Stuff::Point3D actualPosition;
- actualPosition.x = -position.x;
- actualPosition.y = position.z;
- actualPosition.z = position.y;
-
- Stuff::LinearMatrix4D shapeOrigin;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- Stuff::OBB boundingBox;
- gosFX::Effect::ExecuteInfo info((Stuff::Time)scenarioTime,&shapeOrigin,&boundingBox);
-
- bool result = hitEffect->Execute(&info);
- if (!result)
- {
- hitEffect->Kill(); //Effect is over. Otherwise, wait until hit!
- delete hitEffect;
- hitEffect = NULL;
- }
- }
-
- setFlag(OBJECT_FLAG_BOOM, true);
- setFlag(OBJECT_FLAG_TANGIBLE, true);
- }
-
- //----------------------------------------------------------------------------
- // Sensor round is ticking now. Update Everything.
- if ((info.strike.timeToBlind > 0.0) && getFlag(OBJECT_FLAG_SENSORS_GOING))
- {
- info.strike.timeToBlind -= frameLength;
- info.strike.sensorRange = info.strike.timeToBlind / type->nominalSensorTime;
- info.strike.sensorRange *= type->nominalSensorRange;
- info.strike.sensorRange *= worldUnitsPerMeter;
- SensorSystemPtr sensor = SensorManager->getSensor(info.strike.sensorSystemIndex);
- Assert(sensor != NULL, 0, " Artillery.update: NULL sensor ");
- sensor->setRange(info.strike.sensorRange * metersPerWorldUnit);
- //--------------------------------------
- // Actual scan is done in team update...
- }
- else if ((info.strike.timeToBlind <= 0.0) && getFlag(OBJECT_FLAG_SENSORS_GOING))
- {
- //---------------------------------------------------
- // All done, return FALSE;
- SensorSystemPtr sensor = SensorManager->getSensor(info.strike.sensorSystemIndex);
- SensorManager->removeTeamSensor(getTeam()->getId(), sensor);
- SensorManager->freeSensor(sensor);
- return(0);
- }
-
- //-------------------------------------------------------------------------------------------
- // If we are a sensor round, start the sensor countdown. ALWAYS on, even before effect hits.
- // time to blind is being reset everytime without this else
- else if (type->nominalSensorTime > 0)
- {
- info.strike.timeToBlind = type->nominalSensorTime;
- setFlag(OBJECT_FLAG_SENSORS_GOING, true);
- }
- if (type->nominalDamage == 0)
- {
- //-------------------------------------
- // Create the Sensor Probe Landing now
- // GOS Fx now.
- if (hitEffect)
- {
- Stuff::Point3D actualPosition;
- actualPosition.x = -position.x;
- actualPosition.y = position.z;
- actualPosition.z = position.y;
-
- Stuff::LinearMatrix4D shapeOrigin;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- Stuff::OBB boundingBox;
- gosFX::Effect::ExecuteInfo xinfo((Stuff::Time)scenarioTime,&shapeOrigin,&boundingBox);
-
- bool result = hitEffect->Execute(&xinfo);
- if (!result)
- {
- hitEffect->Kill(); //Effect is over. Otherwise, wait until hit!
- delete hitEffect;
- hitEffect = NULL;
- }
- }
- }
-
- return(1);
- }
- //---------------------------------------------------------------------------
- bool Artillery::recalcBounds (CameraPtr myEye)
- {
- if (myEye)
- {
- //--------------------------------------------------
- // First, if we are using perspective, figure out
- // if object too far from camera. Far Clip Plane.
- if (eye->usePerspective)
- {
- Stuff::Point3D Distance;
- Stuff::Point3D objPosition(position);
- Stuff::Point3D eyePosition(eye->getPosition());
-
- Distance.Subtract(objPosition,eyePosition);
- float eyeDistance = Distance.GetApproximateLength();
- if (eyeDistance > Camera::MaxClipDistance)
- {
- inView = false;
- }
- else
- {
- inView = true;
- }
-
- //-----------------------------------------------------------------
- // If inside farClip plane, check if behind camera.
- // Find angle between lookVector of Camera and vector from camPos
- // to Target. If angle is less then halfFOV, object is visible.
- if (inView)
- {
- Stuff::Vector3D Distance;
- Stuff::Point3D objPosition;
- Stuff::Point3D eyePosition(eye->getCameraOrigin());
- objPosition.x = -position.x;
- objPosition.y = position.z;
- objPosition.z = position.y;
-
- Distance.Subtract(objPosition,eyePosition);
- Distance.Normalize(Distance);
-
- float cosine = Distance * eye->getLookVector();
- if (cosine > eye->cosHalfFOV)
- inView = true;
- else
- inView = false;
- }
- }
- else
- {
- inView = true;
- }
-
- if (inView)
- {
- eye->projectZ(position,screenPos);
- Stuff::Vector4D iFaceScreen;
- eye->projectZ(iFacePosition, iFaceScreen );
-
- if ((screenPos.x >= 0) && (screenPos.y >= 0) &&
- (screenPos.x <= eye->getScreenResX()) &&
- (screenPos.y <= eye->getScreenResY())
- || ((iFaceScreen.x >= 0) && (iFaceScreen.y >= 0) &&
- (iFaceScreen.x <= eye->getScreenResX()) &&
- (iFaceScreen.y <= eye->getScreenResY())))
- {
- inView = true;
- }
- else
- {
- inView = false;
- }
- }
- }
-
- return (inView);
- }
- //---------------------------------------------------------------------------
- TeamPtr Artillery::getTeam (void)
- {
- if (teamId == -1)
- return(NULL);
- return(Team::teams[teamId]);
- }
- //---------------------------------------------------------------------------
- void Artillery::setCommanderId (long _commanderId)
- {
- commanderId = _commanderId;
- }
- //---------------------------------------------------------------------------
- long Artillery::setTeamId (long _teamId, bool setup)
- {
- teamId = _teamId;
- Assert(teamId > -1, teamId, " Mover.setTeamId: bad teamId ");
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- bool Artillery::isFriendly (TeamPtr team) {
- if (teamId > -1)
- return(Team::relations[teamId][team->getId()] == RELATION_FRIENDLY);
- return(false);
- }
- //---------------------------------------------------------------------------
- bool Artillery::isEnemy (TeamPtr team) {
- if (teamId > -1)
- return(Team::relations[teamId][team->getId()] == RELATION_ENEMY);
- return(false);
- }
- //---------------------------------------------------------------------------
- bool Artillery::isNeutral (TeamPtr team) {
- if (teamId > -1)
- return(Team::relations[teamId][team->getId()] == RELATION_NEUTRAL);
- return(true);
- }
- //---------------------------------------------------------------------------
- void Artillery::setSensorRange (float range)
- {
- SensorSystemPtr sensor = SensorManager->getSensor(info.strike.sensorSystemIndex);
- if (sensor)
- sensor->setRange(range);
- }
- //---------------------------------------------------------------------------
- void Artillery::setSensorData (TeamPtr team, float sensorTime, float range)
- {
- if (sensorTime != -1.0)
- info.strike.timeToBlind = sensorTime;
-
- if (range != -1.0)
- info.strike.sensorRange = range;
- SensorSystemPtr sensor = SensorManager->getSensor(info.strike.sensorSystemIndex);
- Assert(sensor != NULL, info.strike.sensorSystemIndex, " Artillery.setSensorData: NULL sensor ");
- sensor->setOwner(this);
- SensorManager->addTeamSensor(team->getId(), sensor);
- sensor->setRange(range);
- sensor->setLOSCapability(false);
- }
- //---------------------------------------------------------------------------
- void Artillery::drawSelectBox (unsigned char color)
- {
- }
-
- //---------------------------------------------------------------------------
- void Artillery::render (void)
- {
- if (inView)
- {
- if (hitEffect )
- {
- gosFX::Effect::DrawInfo drawInfo;
- drawInfo.m_clipper = theClipper;
-
- MidLevelRenderer::MLRState mlrState;
- //mlrState.SetBackFaceOn();
- mlrState.SetDitherOn();
- mlrState.SetTextureCorrectionOn();
- mlrState.SetZBufferCompareOn();
- mlrState.SetZBufferWriteOn();
-
- //mlrState.SetFilterMode(MidLevelRenderer::MLRState::BiLinearFilterMode);
- //mlrState.SetAlphaMode(MidLevelRenderer::MLRState::AlphaInvAlphaMode);
-
- drawInfo.m_state = mlrState;
- drawInfo.m_clippingFlags = 0x0;
-
- Stuff::Point3D actualPosition;
- actualPosition.x = -position.x;
- actualPosition.y = position.z;
- actualPosition.z = position.y;
-
- Stuff::LinearMatrix4D shapeOrigin;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- drawInfo.m_parentToWorld = &shapeOrigin;
-
- if (!MLRVertexLimitReached)
- hitEffect->Draw(&drawInfo);
- }
- if ( (!MPlayer && (info.strike.timeToImpact > 0.f)) ||
- (MPlayer && info.strike.timeToImpact > 0.f
- && ((teamId == Team::home->getId()) || info.strike.timeToImpact < 3.0f)))
- {
- // We are drawing the timer.
- // Draw it.
- char text[256];
- switch (artilleryType)
- {
- case ARTILLERY_LARGE:
- sprintf(text,"%02.2f",info.strike.timeToImpact);
- break;
-
- case ARTILLERY_SMALL:
- sprintf(text,"%02.2f",info.strike.timeToImpact);
- break;
-
- case ARTILLERY_SENSOR:
- text[0] = 0; // players are confused by sensor count down
- break;
- }
-
- DWORD width, height;
- Stuff::Vector4D moveHere;
- eye->projectZ( iFacePosition, moveHere );
- gos_TextSetAttributes (gosFontHandle, 0, gosFontScale, false, false, false, false);
- gos_TextStringLength(&width,&height,text);
- moveHere.y += 10.0f;
- moveHere.x -= width / 2;
- moveHere.z = width;
- moveHere.w = height;
-
- globalFloatHelp->setFloatHelp(text,moveHere,SD_GREEN,0x0,gosFontScale,false,false,false,false);
-
- if (appearance->canBeSeen())
- {
- windowsVisible = turn;
- appearance->setVisibility(true,true);
- appearance->render(-1);
- }
- }
- }
-
- if (bomber && bombRunStarted)
- {
- bomber->setVisibility(true,true);
- bomber->render();
- bomber->renderShadows();
-
- gosFX::Effect::DrawInfo drawInfo;
- drawInfo.m_clipper = theClipper;
-
- MidLevelRenderer::MLRState mlrState;
- //mlrState.SetBackFaceOn();
- mlrState.SetDitherOn();
- mlrState.SetTextureCorrectionOn();
- mlrState.SetZBufferCompareOn();
- mlrState.SetZBufferWriteOn();
- //mlrState.SetFilterMode(MidLevelRenderer::MLRState::BiLinearFilterMode);
- //mlrState.SetAlphaMode(MidLevelRenderer::MLRState::AlphaInvAlphaMode);
- drawInfo.m_state = mlrState;
- drawInfo.m_clippingFlags = 0x0;
-
- if (leftContrail)
- {
- Stuff::Vector3D lPosition = bomber->getDustNodePosition(GV_LEFT_DUST_ID);
-
- Stuff::Point3D actualPosition;
- actualPosition.x = -lPosition.x;
- actualPosition.y = lPosition.z;
- actualPosition.z = lPosition.y;
-
- Stuff::LinearMatrix4D shapeOrigin;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- drawInfo.m_parentToWorld = &shapeOrigin;
-
- if (!MLRVertexLimitReached)
- leftContrail->Draw(&drawInfo);
- }
-
- if (rightContrail)
- {
- Stuff::Vector3D lPosition = bomber->getNodeNamePosition("activity_node");
-
- Stuff::Point3D actualPosition;
- actualPosition.x = -lPosition.x;
- actualPosition.y = lPosition.z;
- actualPosition.z = lPosition.y;
-
- Stuff::LinearMatrix4D shapeOrigin;
-
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
-
- drawInfo.m_parentToWorld = &shapeOrigin;
-
- if (!MLRVertexLimitReached)
- rightContrail->Draw(&drawInfo);
- }
- }
- }
- //---------------------------------------------------------------------------
- long Artillery::handleWeaponHit (WeaponShotInfoPtr shotInfo, bool addMultiplayChunk)
- {
- return(NO_ERR);
- }
- //---------------------------------------------------------------------------
- void Artillery::destroy (void)
- {
- //Must delete here too in case effect was NOT over when mission ended!
- if (hitEffect)
- {
- hitEffect->Kill();
- delete hitEffect;
- hitEffect = NULL;
- }
-
- if (leftContrail)
- {
- leftContrail->Kill();
- delete leftContrail;
- leftContrail = NULL;
- }
-
- if (rightContrail)
- {
- rightContrail->Kill();
- delete rightContrail;
- rightContrail = NULL;
- }
- if (bomber)
- {
- delete bomber;
- bomber = NULL;
- }
- }
- //---------------------------------------------------------------------------
- void Artillery::init (bool create, ObjectTypePtr _type)
- {
- GameObject::init(create, _type);
- initFlags();
-
- switch (_type->getObjectTypeClass())
- {
- case ARTILLERY_TYPE:
- objectClass = ARTILLERY;
- setFlag(OBJECT_FLAG_EXISTS, true);
- setFlag(OBJECT_FLAG_JUSTCREATED, true);
- setFlag(OBJECT_FLAG_BOOM, false);
- info.strike.timeToImpact = -1.0;
- info.strike.explosionOffFlags = 0;
- break;
- }
- effectId = -1;
- switch (_type->whatAmI())
- {
- case BIG_ARTLRY:
- {
- effectId = LARGE_AIRSTRIKE_ID;
- init(ARTILLERY_LARGE);
-
- //--------------------------------------------
- //Load up the strike appearance before hit.
- char appearName[1024];
- strcpy(appearName,AIRSTRIKE_NAME);
-
- //--------------------------------------------------------------
- // New code!!!
- // We need to append the sprite type to the appearance num now.
- // The MechEdit tool does not assume a sprite type, nor should it.
- // MechCmdr2 features much simpler objects which only use 1 type of sprite!
- long appearanceType = (BLDG_TYPE << 24);
-
- AppearanceTypePtr buildingAppearanceType = NULL;
- if (!appearName)
- {
- //------------------------------------------------------
- // LOAD a dummy appearance until real ones are available
- // for this building!
- appearanceType = (BLDG_TYPE << 24);
- buildingAppearanceType = appearanceTypeList->getAppearance(appearanceType,"TESTBLDG");
- }
- else
- {
- buildingAppearanceType = appearanceTypeList->getAppearance(appearanceType,appearName);
- if (!buildingAppearanceType)
- {
- char msg[1024];
- sprintf(msg,"No Building Appearance Named %s",appearName);
- Fatal(0,msg);
- }
- }
-
- appearance = new BldgAppearance;
- gosASSERT(appearance != NULL);
-
- //--------------------------------------------------------------
- // The only appearance type for buildings is MLR_APPEARANCE.
- gosASSERT(buildingAppearanceType->getAppearanceClass() == BLDG_TYPE);
-
- appearance->init((BldgAppearanceType*)buildingAppearanceType, (GameObjectPtr)this);
-
- //--------------------------------------------------------------
- appearanceType = (GV_TYPE << 24);
-
- AppearanceTypePtr bomberAppearanceType = appearanceTypeList->getAppearance(appearanceType,"Shilone");
- if (!bomberAppearanceType)
- {
- STOP(("Unable to create Bomber for air strike Shilone"));
- }
-
- if ((appearanceType>>24) == GV_TYPE)
- {
- bomber = new GVAppearance;
- if (!bomber)
- STOP((" Artillery.init: unable to create appearance for Shilone"));
-
- //-----------------------------------------------------------------
- bomber->init((GVAppearanceType*)bomberAppearanceType, (GameObjectPtr)this);
- }
-
- bombRunStarted = false;
- }
- break;
-
- case SMALL_ARTLRY:
- {
- effectId = SMALL_AIRSTRIKE_ID;
- init(ARTILLERY_SMALL);
- //--------------------------------------------
- //Load up the strike appearance before hit.
- char appearName[1024];
- strcpy(appearName,AIRSTRIKE_NAME);
-
- //--------------------------------------------------------------
- // New code!!!
- // We need to append the sprite type to the appearance num now.
- // The MechEdit tool does not assume a sprite type, nor should it.
- // MechCmdr2 features much simpler objects which only use 1 type of sprite!
- long appearanceType = (BLDG_TYPE << 24);
-
- AppearanceTypePtr buildingAppearanceType = NULL;
- if (!appearName)
- {
- //------------------------------------------------------
- // LOAD a dummy appearance until real ones are available
- // for this building!
- appearanceType = (BLDG_TYPE << 24);
- buildingAppearanceType = appearanceTypeList->getAppearance(appearanceType,"TESTBLDG");
- }
- else
- {
- buildingAppearanceType = appearanceTypeList->getAppearance(appearanceType,appearName);
- if (!buildingAppearanceType)
- {
- char msg[1024];
- sprintf(msg,"No Building Appearance Named %s",appearName);
- Fatal(0,msg);
- }
- }
-
- appearance = new BldgAppearance;
- gosASSERT(appearance != NULL);
-
- //--------------------------------------------------------------
- // The only appearance type for buildings is MLR_APPEARANCE.
- gosASSERT(buildingAppearanceType->getAppearanceClass() == BLDG_TYPE);
-
- appearance->init((BldgAppearanceType*)buildingAppearanceType, (GameObjectPtr)this);
- //--------------------------------------------------------------
- appearanceType = (GV_TYPE << 24);
-
- AppearanceTypePtr bomberAppearanceType = appearanceTypeList->getAppearance(appearanceType,"shilone");
- if (!bomberAppearanceType)
- {
- STOP(("Unable to create Bomber for air strike Shilone"));
- }
-
- if ((appearanceType>>24) == GV_TYPE)
- {
- bomber = new GVAppearance;
- if (!bomber)
- STOP((" Artillery.init: unable to create appearance for Shilone"));
-
- //-----------------------------------------------------------------
- bomber->init((GVAppearanceType*)bomberAppearanceType, (GameObjectPtr)this);
- }
-
- bombRunStarted = false;
- }
- break;
-
- case SENSOR_ARTLRY:
- {
- effectId = SENSOR_AIRSTRIKE_ID;
- init(create, ARTILLERY_SENSOR);
- //--------------------------------------------
- //Load up the strike appearance before hit.
-
- char appearName[1024];
- strcpy(appearName,SENSOR_NAME);
-
- //--------------------------------------------------------------
- // New code!!!
- // We need to append the sprite type to the appearance num now.
- // The MechEdit tool does not assume a sprite type, nor should it.
- // MechCmdr2 features much simpler objects which only use 1 type of sprite!
- long appearanceType = (BLDG_TYPE << 24);
-
- AppearanceTypePtr buildingAppearanceType = NULL;
- if (!appearName)
- {
- //------------------------------------------------------
- // LOAD a dummy appearance until real ones are available
- // for this building!
- appearanceType = (BLDG_TYPE << 24);
- buildingAppearanceType = appearanceTypeList->getAppearance(appearanceType,"TESTBLDG");
- }
- else
- {
- buildingAppearanceType = appearanceTypeList->getAppearance(appearanceType,appearName);
- if (!buildingAppearanceType)
- {
- char msg[1024];
- sprintf(msg,"No Building Appearance Named %s",appearName);
- Fatal(0,msg);
- }
- }
-
- appearance = new BldgAppearance;
- gosASSERT(appearance != NULL);
-
- //--------------------------------------------------------------
- // The only appearance type for buildings is MLR_APPEARANCE.
- gosASSERT(buildingAppearanceType->getAppearanceClass() == BLDG_TYPE);
-
- appearance->init((BldgAppearanceType*)buildingAppearanceType, (GameObjectPtr)this);
- }
- break;
- }
- }
- //---------------------------------------------------------------------------
- void Artillery::Save (PacketFilePtr file, long packetNum)
- {
- ArtilleryData data;
- CopyTo(&data);
- //PacketNum incremented in ObjectManager!!
- file->writePacket(packetNum,(MemoryPtr)&data,sizeof(ArtilleryData),STORAGE_TYPE_ZLIB);
- }
- //---------------------------------------------------------------------------
- void Artillery::CopyTo (ArtilleryData *data)
- {
- data->artilleryType = artilleryType;
- data->teamId = teamId;
- data->commanderId = commanderId;
- data->info = info;
- data->effectId = effectId;
- data->bombRunStarted = bombRunStarted;
- data->inView = inView;
- data->iFacePosition = iFacePosition;
- GameObject::CopyTo(dynamic_cast<GameObjectData *>(data));
- }
- //---------------------------------------------------------------------------
- void Artillery::Load (ArtilleryData *data)
- {
- GameObject::Load(dynamic_cast<GameObjectData *>(data));
- artilleryType = data->artilleryType;
- commanderId = data->commanderId;
- teamId = data->teamId;
- info = data->info;
- effectId = data->effectId;
- bombRunStarted = data->bombRunStarted;
- inView = data->inView;
- iFacePosition = data->iFacePosition;
- // if we're not a true artillery round, we're a sensor probe.
- // This checks to see if we've hit yet.
- // If not, create the impact effect and move on.
- if ((data->info.strike.sensorRange != 0.0f) && (data->info.strike.timeToImpact <= 0.0) && !getFlag(OBJECT_FLAG_SENSORS_GOING))
- {
- long cellR, cellC;
- land->worldToCell(position,cellR, cellC);
- if (GameMap->getDeepWater(cellR, cellC) || GameMap->getShallowWater(cellR, cellC))
- effectId--;
-
- //Create the GOSFX here.
- if (strcmp(weaponEffects->GetEffectName(effectId),"NONE") != 0)
- {
- //--------------------------------------------
- // Yes, load it on up.
- unsigned flags = gosFX::Effect::ExecuteFlag;
-
- Check_Object(gosFX::EffectLibrary::Instance);
- gosFX::Effect::Specification* gosEffectSpec = gosFX::EffectLibrary::Instance->Find(weaponEffects->GetEffectName(effectId));
-
- if (gosEffectSpec)
- {
- hitEffect = gosFX::EffectLibrary::Instance->MakeEffect(gosEffectSpec->m_effectID, flags);
- gosASSERT(hitEffect != NULL);
-
- MidLevelRenderer::MLRTexturePool::Instance->LoadImages();
- }
- }
- if (hitEffect)
- {
- Stuff::LinearMatrix4D shapeOrigin;
- Stuff::Point3D actualPosition;
- actualPosition.x = -position.x;
- actualPosition.y = position.z;
- actualPosition.z = position.y;
- shapeOrigin.BuildRotation(Stuff::EulerAngles(0.0f,0.0f,0.0f));
- shapeOrigin.BuildTranslation(actualPosition);
- gosFX::Effect::ExecuteInfo info((Stuff::Time)scenarioTime,&shapeOrigin,NULL);
- hitEffect->Start(&info);
- }
- }
- if (!getFlag(OBJECT_FLAG_BOOM) && (data->info.strike.timeToImpact > 0.0) && (data->info.strike.sensorRange == 0.0f))
- {
- //Create the GOSFX here.
- if (strcmp(weaponEffects->GetEffectName(effectId),"NONE") != 0)
- {
- //--------------------------------------------
- // Yes, load it on up.
- unsigned flags = gosFX::Effect::ExecuteFlag;
-
- Check_Object(gosFX::EffectLibrary::Instance);
- gosFX::Effect::Specification* gosEffectSpec = gosFX::EffectLibrary::Instance->Find(weaponEffects->GetEffectName(effectId));
-
- if (gosEffectSpec)
- {
- hitEffect = gosFX::EffectLibrary::Instance->MakeEffect(gosEffectSpec->m_effectID, flags);
- gosASSERT(hitEffect != NULL);
-
- MidLevelRenderer::MLRTexturePool::Instance->LoadImages();
- }
- }
- }
- if (data->info.strike.sensorSystemIndex != -1)
- {
- SensorSystemPtr sensor = SensorManager->newSensor();
- info.strike.sensorSystemIndex = sensor->id;
- setSensorData(getTeam());
- }
- }
- //---------------------------------------------------------------------------
|